authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-12 22:50:50-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-06-12 22:50:50-07:00
log529ef75101e21bd45402c516138343b4770238eb
tree56c925bd7df84e5f223c31a7c8fa90606c8e2dc9
parent1e7dcaa3ae57294ab5998b44a8c13ccc5019e7ea
parent2ad073ec6d4e2be967f18c9907844404a7eed42e
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #15569 from ziglang/intern-pool-3

Use InternPool for all types and constant values

76 files changed, 29849 insertions(+), 28510 deletions(-)

build.zig+2
......@@ -30,6 +30,7 @@ pub fn build(b: *std.Build) !void {
3030 const test_step = b.step("test", "Run all the tests");
3131 const skip_install_lib_files = b.option(bool, "no-lib", "skip copying of lib/ files and langref to installation prefix. Useful for development") orelse false;
3232 const skip_install_langref = b.option(bool, "no-langref", "skip copying of langref to the installation prefix") orelse skip_install_lib_files;
33 const no_bin = b.option(bool, "no-bin", "skip emitting compiler binary") orelse false;
3334
3435 const docgen_exe = b.addExecutable(.{
3536 .name = "docgen",
......@@ -166,6 +167,7 @@ pub fn build(b: *std.Build) !void {
166167 exe.pie = pie;
167168 exe.sanitize_thread = sanitize_thread;
168169 exe.entitlements = entitlements;
170 if (no_bin) exe.emit_bin = .no_emit;
169171
170172 exe.build_id = b.option(
171173 std.Build.Step.Compile.BuildId,
doc/langref.html.in+1-1
......@@ -10176,7 +10176,7 @@ pub fn main() void {
1017610176
1017710177 {#header_open|Invalid Error Set Cast#}
1017810178 <p>At compile-time:</p>
10179 {#code_begin|test_err|test_comptime_invalid_error_set_cast|'error.B' not a member of error set 'error{A,C}'#}
10179 {#code_begin|test_err|test_comptime_invalid_error_set_cast|'error.B' not a member of error set 'error{C,A}'#}
1018010180const Set1 = error{
1018110181 A,
1018210182 B,
lib/std/array_list.zig+44
......@@ -459,6 +459,28 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
459459 return self.items[prev_len..][0..n];
460460 }
461461
462 /// Resize the array, adding `n` new elements, which have `undefined` values.
463 /// The return value is a slice pointing to the newly allocated elements.
464 /// The returned pointer becomes invalid when the list is resized.
465 /// Resizes list if `self.capacity` is not large enough.
466 pub fn addManyAsSlice(self: *Self, n: usize) Allocator.Error![]T {
467 const prev_len = self.items.len;
468 try self.resize(self.items.len + n);
469 return self.items[prev_len..][0..n];
470 }
471
472 /// Resize the array, adding `n` new elements, which have `undefined` values.
473 /// The return value is a slice pointing to the newly allocated elements.
474 /// Asserts that there is already space for the new item without allocating more.
475 /// **Does not** invalidate element pointers.
476 /// The returned pointer becomes invalid when the list is resized.
477 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
478 assert(self.items.len + n <= self.capacity);
479 const prev_len = self.items.len;
480 self.items.len += n;
481 return self.items[prev_len..][0..n];
482 }
483
462484 /// Remove and return the last element from the list.
463485 /// Asserts the list has at least one item.
464486 /// Invalidates pointers to the removed element.
......@@ -949,6 +971,28 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
949971 return self.items[prev_len..][0..n];
950972 }
951973
974 /// Resize the array, adding `n` new elements, which have `undefined` values.
975 /// The return value is a slice pointing to the newly allocated elements.
976 /// The returned pointer becomes invalid when the list is resized.
977 /// Resizes list if `self.capacity` is not large enough.
978 pub fn addManyAsSlice(self: *Self, allocator: Allocator, n: usize) Allocator.Error![]T {
979 const prev_len = self.items.len;
980 try self.resize(allocator, self.items.len + n);
981 return self.items[prev_len..][0..n];
982 }
983
984 /// Resize the array, adding `n` new elements, which have `undefined` values.
985 /// The return value is a slice pointing to the newly allocated elements.
986 /// Asserts that there is already space for the new item without allocating more.
987 /// **Does not** invalidate element pointers.
988 /// The returned pointer becomes invalid when the list is resized.
989 pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T {
990 assert(self.items.len + n <= self.capacity);
991 const prev_len = self.items.len;
992 self.items.len += n;
993 return self.items[prev_len..][0..n];
994 }
995
952996 /// Remove and return the last element from the list.
953997 /// Asserts the list has at least one item.
954998 /// Invalidates pointers to last element.
lib/std/builtin.zig+3-3
......@@ -143,7 +143,7 @@ pub const Mode = OptimizeMode;
143143
144144/// This data structure is used by the Zig language code generation and
145145/// therefore must be kept in sync with the compiler implementation.
146pub const CallingConvention = enum {
146pub const CallingConvention = enum(u8) {
147147 /// This is the default Zig calling convention used when not using `export` on `fn`
148148 /// and no other calling convention is specified.
149149 Unspecified,
......@@ -190,7 +190,7 @@ pub const CallingConvention = enum {
190190
191191/// This data structure is used by the Zig language code generation and
192192/// therefore must be kept in sync with the compiler implementation.
193pub const AddressSpace = enum {
193pub const AddressSpace = enum(u5) {
194194 generic,
195195 gs,
196196 fs,
......@@ -283,7 +283,7 @@ pub const Type = union(enum) {
283283
284284 /// This data structure is used by the Zig language code generation and
285285 /// therefore must be kept in sync with the compiler implementation.
286 pub const Size = enum {
286 pub const Size = enum(u2) {
287287 One,
288288 Many,
289289 Slice,
lib/std/child_process.zig+2-2
......@@ -530,7 +530,7 @@ pub const ChildProcess = struct {
530530 // can fail between fork() and execve().
531531 // Therefore, we do all the allocation for the execve() before the fork().
532532 // This means we must do the null-termination of argv and env vars here.
533 const argv_buf = try arena.allocSentinel(?[*:0]u8, self.argv.len, null);
533 const argv_buf = try arena.allocSentinel(?[*:0]const u8, self.argv.len, null);
534534 for (self.argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
535535
536536 const envp = m: {
......@@ -542,7 +542,7 @@ pub const ChildProcess = struct {
542542 } else if (builtin.output_mode == .Exe) {
543543 // Then we have Zig start code and this works.
544544 // TODO type-safety for null-termination of `os.environ`.
545 break :m @ptrCast([*:null]?[*:0]u8, os.environ.ptr);
545 break :m @ptrCast([*:null]const ?[*:0]const u8, os.environ.ptr);
546546 } else {
547547 // TODO come up with a solution for this.
548548 @compileError("missing std lib enhancement: ChildProcess implementation has no way to collect the environment variables to forward to the child process");
lib/std/crypto/tls/Client.zig+2-4
......@@ -1256,10 +1256,8 @@ fn limitedOverlapCopy(frag: []u8, in: usize) void {
12561256 // A single, non-overlapping memcpy suffices.
12571257 @memcpy(frag[0..first.len], first);
12581258 } else {
1259 // Need two memcpy calls because one alone would overlap.
1260 @memcpy(frag[0..in], first[0..in]);
1261 const leftover = first.len - in;
1262 @memcpy(frag[in..][0..leftover], first[in..][0..leftover]);
1259 // One memcpy call would overlap, so just do this instead.
1260 std.mem.copyForwards(u8, frag, first);
12631261 }
12641262}
12651263
lib/std/dwarf.zig+1
......@@ -936,6 +936,7 @@ pub const DwarfInfo = struct {
936936 const ranges_val = compile_unit.die.getAttr(AT.ranges) orelse continue;
937937 const ranges_offset = switch (ranges_val.*) {
938938 .SecOffset => |off| off,
939 .Const => |c| try c.asUnsignedLe(),
939940 .RangeListOffset => |idx| off: {
940941 if (compile_unit.is_64) {
941942 const offset_loc = @intCast(usize, compile_unit.rnglists_base + 8 * idx);
lib/std/hash.zig+14
......@@ -36,6 +36,20 @@ const xxhash = @import("hash/xxhash.zig");
3636pub const XxHash64 = xxhash.XxHash64;
3737pub const XxHash32 = xxhash.XxHash32;
3838
39/// This is handy if you have a u32 and want a u32 and don't want to take a
40/// detour through many layers of abstraction elsewhere in the std.hash
41/// namespace.
42/// Copied from https://nullprogram.com/blog/2018/07/31/
43pub fn uint32(input: u32) u32 {
44 var x: u32 = input;
45 x ^= x >> 16;
46 x *%= 0x7feb352d;
47 x ^= x >> 15;
48 x *%= 0x846ca68b;
49 x ^= x >> 16;
50 return x;
51}
52
3953test {
4054 _ = adler;
4155 _ = auto_hash;
lib/std/hash/auto_hash.zig+15-9
......@@ -91,15 +91,21 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
9191
9292 // Help the optimizer see that hashing an int is easy by inlining!
9393 // TODO Check if the situation is better after #561 is resolved.
94 .Int => {
95 if (comptime meta.trait.hasUniqueRepresentation(Key)) {
96 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });
97 } else {
98 // Take only the part containing the key value, the remaining
99 // bytes are undefined and must not be hashed!
100 const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Key), 8) catch unreachable;
101 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key)[0..byte_size] });
102 }
94 .Int => |int| switch (int.signedness) {
95 .signed => hash(hasher, @bitCast(@Type(.{ .Int = .{
96 .bits = int.bits,
97 .signedness = .unsigned,
98 } }), key), strat),
99 .unsigned => {
100 if (comptime meta.trait.hasUniqueRepresentation(Key)) {
101 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key) });
102 } else {
103 // Take only the part containing the key value, the remaining
104 // bytes are undefined and must not be hashed!
105 const byte_size = comptime std.math.divCeil(comptime_int, @bitSizeOf(Key), 8) catch unreachable;
106 @call(.always_inline, Hasher.update, .{ hasher, std.mem.asBytes(&key)[0..byte_size] });
107 }
108 },
103109 },
104110
105111 .Bool => hash(hasher, @boolToInt(key), strat),
lib/std/math/big/int.zig+5-2
......@@ -2158,6 +2158,9 @@ pub const Const = struct {
21582158 pub fn to(self: Const, comptime T: type) ConvertError!T {
21592159 switch (@typeInfo(T)) {
21602160 .Int => |info| {
2161 // Make sure -0 is handled correctly.
2162 if (self.eqZero()) return 0;
2163
21612164 const UT = std.meta.Int(.unsigned, info.bits);
21622165
21632166 if (!self.fitsInTwosComp(info.signedness, info.bits)) {
......@@ -2509,7 +2512,7 @@ pub const Const = struct {
25092512 return total_limb_lz + bits - total_limb_bits;
25102513 }
25112514
2512 pub fn ctz(a: Const) Limb {
2515 pub fn ctz(a: Const, bits: Limb) Limb {
25132516 // Limbs are stored in little-endian order.
25142517 var result: Limb = 0;
25152518 for (a.limbs) |limb| {
......@@ -2517,7 +2520,7 @@ pub const Const = struct {
25172520 result += limb_tz;
25182521 if (limb_tz != @sizeOf(Limb) * 8) break;
25192522 }
2520 return result;
2523 return @min(result, bits);
25212524 }
25222525};
25232526
lib/std/mem.zig+2-1
......@@ -4226,7 +4226,8 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize {
42264226/// The alignment must be a power of 2 and greater than 0.
42274227/// Asserts that rounding up the address does not cause integer overflow.
42284228pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {
4229 assert(isValidAlignGeneric(T, alignment));
4229 assert(alignment > 0);
4230 assert(std.math.isPowerOfTwo(alignment));
42304231 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);
42314232}
42324233
lib/std/process.zig+2-2
......@@ -1131,7 +1131,7 @@ pub fn execve(
11311131 defer arena_allocator.deinit();
11321132 const arena = arena_allocator.allocator();
11331133
1134 const argv_buf = try arena.allocSentinel(?[*:0]u8, argv.len, null);
1134 const argv_buf = try arena.allocSentinel(?[*:0]const u8, argv.len, null);
11351135 for (argv, 0..) |arg, i| argv_buf[i] = (try arena.dupeZ(u8, arg)).ptr;
11361136
11371137 const envp = m: {
......@@ -1143,7 +1143,7 @@ pub fn execve(
11431143 } else if (builtin.output_mode == .Exe) {
11441144 // Then we have Zig start code and this works.
11451145 // TODO type-safety for null-termination of `os.environ`.
1146 break :m @ptrCast([*:null]?[*:0]u8, os.environ.ptr);
1146 break :m @ptrCast([*:null]const ?[*:0]const u8, os.environ.ptr);
11471147 } else {
11481148 // TODO come up with a solution for this.
11491149 @compileError("missing std lib enhancement: std.process.execv implementation has no way to collect the environment variables to forward to the child process");
src/Air.zig+200-71
......@@ -5,16 +5,18 @@
55
66const std = @import("std");
77const builtin = @import("builtin");
8const Value = @import("value.zig").Value;
9const Type = @import("type.zig").Type;
108const assert = std.debug.assert;
9
1110const Air = @This();
11const Value = @import("value.zig").Value;
12const Type = @import("type.zig").Type;
13const InternPool = @import("InternPool.zig");
14const Module = @import("Module.zig");
1215
1316instructions: std.MultiArrayList(Inst).Slice,
1417/// The meaning of this data is determined by `Inst.Tag` value.
1518/// The first few indexes are reserved. See `ExtraIndex` for the values.
1619extra: []const u32,
17values: []const Value,
1820
1921pub const ExtraIndex = enum(u32) {
2022 /// Payload index of the main `Block` in the `extra` array.
......@@ -183,6 +185,18 @@ pub const Inst = struct {
183185 /// Allocates stack local memory.
184186 /// Uses the `ty` field.
185187 alloc,
188 /// This special instruction only exists temporarily during semantic
189 /// analysis and is guaranteed to be unreachable in machine code
190 /// backends. It tracks a set of types that have been stored to an
191 /// inferred allocation.
192 /// Uses the `inferred_alloc` field.
193 inferred_alloc,
194 /// This special instruction only exists temporarily during semantic
195 /// analysis and is guaranteed to be unreachable in machine code
196 /// backends. Used to coordinate alloc_inferred, store_to_inferred_ptr,
197 /// and resolve_inferred_alloc instructions for comptime code.
198 /// Uses the `inferred_alloc_comptime` field.
199 inferred_alloc_comptime,
186200 /// If the function will pass the result by-ref, this instruction returns the
187201 /// result pointer. Otherwise it is equivalent to `alloc`.
188202 /// Uses the `ty` field.
......@@ -394,11 +408,9 @@ pub const Inst = struct {
394408 /// was executed on the operand.
395409 /// Uses the `ty_pl` field. Payload is `TryPtr`.
396410 try_ptr,
397 /// A comptime-known value. Uses the `ty_pl` field, payload is index of
398 /// `values` array.
399 constant,
400 /// A comptime-known type. Uses the `ty` field.
401 const_ty,
411 /// A comptime-known value via an index into the InternPool.
412 /// Uses the `interned` field.
413 interned,
402414 /// Notes the beginning of a source code statement and marks the line and column.
403415 /// Result type is always void.
404416 /// Uses the `dbg_stmt` field.
......@@ -408,10 +420,10 @@ pub const Inst = struct {
408420 /// Marks the end of a semantic scope for debug info variables.
409421 dbg_block_end,
410422 /// Marks the start of an inline call.
411 /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.
423 /// Uses the `ty_fn` field.
412424 dbg_inline_begin,
413425 /// Marks the end of an inline call.
414 /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.
426 /// Uses the `ty_fn` field.
415427 dbg_inline_end,
416428 /// Marks the beginning of a local variable. The operand is a pointer pointing
417429 /// to the storage for the variable. The local may be a const or a var.
......@@ -837,7 +849,96 @@ pub const Inst = struct {
837849 /// The position of an AIR instruction within the `Air` instructions array.
838850 pub const Index = u32;
839851
840 pub const Ref = @import("Zir.zig").Inst.Ref;
852 pub const Ref = enum(u32) {
853 u1_type = @enumToInt(InternPool.Index.u1_type),
854 u8_type = @enumToInt(InternPool.Index.u8_type),
855 i8_type = @enumToInt(InternPool.Index.i8_type),
856 u16_type = @enumToInt(InternPool.Index.u16_type),
857 i16_type = @enumToInt(InternPool.Index.i16_type),
858 u29_type = @enumToInt(InternPool.Index.u29_type),
859 u32_type = @enumToInt(InternPool.Index.u32_type),
860 i32_type = @enumToInt(InternPool.Index.i32_type),
861 u64_type = @enumToInt(InternPool.Index.u64_type),
862 i64_type = @enumToInt(InternPool.Index.i64_type),
863 u80_type = @enumToInt(InternPool.Index.u80_type),
864 u128_type = @enumToInt(InternPool.Index.u128_type),
865 i128_type = @enumToInt(InternPool.Index.i128_type),
866 usize_type = @enumToInt(InternPool.Index.usize_type),
867 isize_type = @enumToInt(InternPool.Index.isize_type),
868 c_char_type = @enumToInt(InternPool.Index.c_char_type),
869 c_short_type = @enumToInt(InternPool.Index.c_short_type),
870 c_ushort_type = @enumToInt(InternPool.Index.c_ushort_type),
871 c_int_type = @enumToInt(InternPool.Index.c_int_type),
872 c_uint_type = @enumToInt(InternPool.Index.c_uint_type),
873 c_long_type = @enumToInt(InternPool.Index.c_long_type),
874 c_ulong_type = @enumToInt(InternPool.Index.c_ulong_type),
875 c_longlong_type = @enumToInt(InternPool.Index.c_longlong_type),
876 c_ulonglong_type = @enumToInt(InternPool.Index.c_ulonglong_type),
877 c_longdouble_type = @enumToInt(InternPool.Index.c_longdouble_type),
878 f16_type = @enumToInt(InternPool.Index.f16_type),
879 f32_type = @enumToInt(InternPool.Index.f32_type),
880 f64_type = @enumToInt(InternPool.Index.f64_type),
881 f80_type = @enumToInt(InternPool.Index.f80_type),
882 f128_type = @enumToInt(InternPool.Index.f128_type),
883 anyopaque_type = @enumToInt(InternPool.Index.anyopaque_type),
884 bool_type = @enumToInt(InternPool.Index.bool_type),
885 void_type = @enumToInt(InternPool.Index.void_type),
886 type_type = @enumToInt(InternPool.Index.type_type),
887 anyerror_type = @enumToInt(InternPool.Index.anyerror_type),
888 comptime_int_type = @enumToInt(InternPool.Index.comptime_int_type),
889 comptime_float_type = @enumToInt(InternPool.Index.comptime_float_type),
890 noreturn_type = @enumToInt(InternPool.Index.noreturn_type),
891 anyframe_type = @enumToInt(InternPool.Index.anyframe_type),
892 null_type = @enumToInt(InternPool.Index.null_type),
893 undefined_type = @enumToInt(InternPool.Index.undefined_type),
894 enum_literal_type = @enumToInt(InternPool.Index.enum_literal_type),
895 atomic_order_type = @enumToInt(InternPool.Index.atomic_order_type),
896 atomic_rmw_op_type = @enumToInt(InternPool.Index.atomic_rmw_op_type),
897 calling_convention_type = @enumToInt(InternPool.Index.calling_convention_type),
898 address_space_type = @enumToInt(InternPool.Index.address_space_type),
899 float_mode_type = @enumToInt(InternPool.Index.float_mode_type),
900 reduce_op_type = @enumToInt(InternPool.Index.reduce_op_type),
901 call_modifier_type = @enumToInt(InternPool.Index.call_modifier_type),
902 prefetch_options_type = @enumToInt(InternPool.Index.prefetch_options_type),
903 export_options_type = @enumToInt(InternPool.Index.export_options_type),
904 extern_options_type = @enumToInt(InternPool.Index.extern_options_type),
905 type_info_type = @enumToInt(InternPool.Index.type_info_type),
906 manyptr_u8_type = @enumToInt(InternPool.Index.manyptr_u8_type),
907 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),
908 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),
909 single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type),
910 slice_const_u8_type = @enumToInt(InternPool.Index.slice_const_u8_type),
911 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
912 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
913 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
914 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),
915 undef = @enumToInt(InternPool.Index.undef),
916 zero = @enumToInt(InternPool.Index.zero),
917 zero_usize = @enumToInt(InternPool.Index.zero_usize),
918 zero_u8 = @enumToInt(InternPool.Index.zero_u8),
919 one = @enumToInt(InternPool.Index.one),
920 one_usize = @enumToInt(InternPool.Index.one_usize),
921 one_u8 = @enumToInt(InternPool.Index.one_u8),
922 four_u8 = @enumToInt(InternPool.Index.four_u8),
923 negative_one = @enumToInt(InternPool.Index.negative_one),
924 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),
925 calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline),
926 void_value = @enumToInt(InternPool.Index.void_value),
927 unreachable_value = @enumToInt(InternPool.Index.unreachable_value),
928 null_value = @enumToInt(InternPool.Index.null_value),
929 bool_true = @enumToInt(InternPool.Index.bool_true),
930 bool_false = @enumToInt(InternPool.Index.bool_false),
931 empty_struct = @enumToInt(InternPool.Index.empty_struct),
932 generic_poison = @enumToInt(InternPool.Index.generic_poison),
933
934 /// This Ref does not correspond to any AIR instruction or constant
935 /// value. It is used to handle argument types of var args functions.
936 var_args_param_type = @enumToInt(InternPool.Index.var_args_param_type),
937 /// This Ref does not correspond to any AIR instruction or constant
938 /// value and may instead be used as a sentinel to indicate null.
939 none = @enumToInt(InternPool.Index.none),
940 _,
941 };
841942
842943 /// All instructions have an 8-byte payload, which is contained within
843944 /// this union. `Tag` determines which union field is active, as well as
......@@ -845,6 +946,7 @@ pub const Inst = struct {
845946 pub const Data = union {
846947 no_op: void,
847948 un_op: Ref,
949 interned: InternPool.Index,
848950
849951 bin_op: struct {
850952 lhs: Ref,
......@@ -864,6 +966,10 @@ pub const Inst = struct {
864966 // Index into a different array.
865967 payload: u32,
866968 },
969 ty_fn: struct {
970 ty: Ref,
971 func: Module.Fn.Index,
972 },
867973 br: struct {
868974 block_inst: Index,
869975 operand: Ref,
......@@ -896,6 +1002,19 @@ pub const Inst = struct {
8961002 // Index into a different array.
8971003 payload: u32,
8981004 },
1005 inferred_alloc_comptime: InferredAllocComptime,
1006 inferred_alloc: InferredAlloc,
1007
1008 pub const InferredAllocComptime = struct {
1009 decl_index: Module.Decl.Index,
1010 alignment: InternPool.Alignment,
1011 is_const: bool,
1012 };
1013
1014 pub const InferredAlloc = struct {
1015 alignment: InternPool.Alignment,
1016 is_const: bool,
1017 };
8991018
9001019 // Make sure we don't accidentally add a field to make this union
9011020 // bigger than expected. Note that in Debug builds, Zig is allowed
......@@ -974,8 +1093,7 @@ pub const FieldParentPtr = struct {
9741093pub const Shuffle = struct {
9751094 a: Inst.Ref,
9761095 b: Inst.Ref,
977 // index to air_values
978 mask: u32,
1096 mask: InternPool.Index,
9791097 mask_len: u32,
9801098};
9811099
......@@ -1064,15 +1182,15 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {
10641182 return air.extra[extra.end..][0..extra.data.body_len];
10651183}
10661184
1067pub fn typeOf(air: Air, inst: Air.Inst.Ref) Type {
1185pub fn typeOf(air: Air, inst: Air.Inst.Ref, ip: *const InternPool) Type {
10681186 const ref_int = @enumToInt(inst);
1069 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
1070 return Air.Inst.Ref.typed_value_map[ref_int].ty;
1187 if (ref_int < InternPool.static_keys.len) {
1188 return InternPool.static_keys[ref_int].typeOf().toType();
10711189 }
1072 return air.typeOfIndex(@intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len));
1190 return air.typeOfIndex(ref_int - ref_start_index, ip);
10731191}
10741192
1075pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
1193pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: *const InternPool) Type {
10761194 const datas = air.instructions.items(.data);
10771195 switch (air.instructions.items(.tag)[inst]) {
10781196 .add,
......@@ -1114,7 +1232,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11141232 .div_exact_optimized,
11151233 .rem_optimized,
11161234 .mod_optimized,
1117 => return air.typeOf(datas[inst].bin_op.lhs),
1235 => return air.typeOf(datas[inst].bin_op.lhs, ip),
11181236
11191237 .sqrt,
11201238 .sin,
......@@ -1132,7 +1250,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11321250 .trunc_float,
11331251 .neg,
11341252 .neg_optimized,
1135 => return air.typeOf(datas[inst].un_op),
1253 => return air.typeOf(datas[inst].un_op, ip),
11361254
11371255 .cmp_lt,
11381256 .cmp_lte,
......@@ -1159,8 +1277,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11591277 .error_set_has_value,
11601278 => return Type.bool,
11611279
1162 .const_ty => return Type.type,
1163
11641280 .alloc,
11651281 .ret_ptr,
11661282 .err_return_trace,
......@@ -1171,7 +1287,6 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11711287
11721288 .assembly,
11731289 .block,
1174 .constant,
11751290 .struct_field_ptr,
11761291 .struct_field_val,
11771292 .slice_elem_ptr,
......@@ -1194,6 +1309,8 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
11941309 .try_ptr,
11951310 => return air.getRefType(datas[inst].ty_pl.ty),
11961311
1312 .interned => return ip.typeOf(datas[inst].interned).toType(),
1313
11971314 .not,
11981315 .bitcast,
11991316 .load,
......@@ -1243,7 +1360,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
12431360 .ret_load,
12441361 .unreach,
12451362 .trap,
1246 => return Type.initTag(.noreturn),
1363 => return Type.noreturn,
12471364
12481365 .breakpoint,
12491366 .dbg_stmt,
......@@ -1280,63 +1397,67 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
12801397 .wasm_memory_grow => return Type.i32,
12811398 .wasm_memory_size => return Type.u32,
12821399
1283 .bool_to_int => return Type.initTag(.u1),
1400 .bool_to_int => return Type.u1,
12841401
1285 .tag_name, .error_name => return Type.initTag(.const_slice_u8_sentinel_0),
1402 .tag_name, .error_name => return Type.slice_const_u8_sentinel_0,
12861403
12871404 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
1288 const callee_ty = air.typeOf(datas[inst].pl_op.operand);
1289 switch (callee_ty.zigTypeTag()) {
1290 .Fn => return callee_ty.fnReturnType(),
1291 .Pointer => return callee_ty.childType().fnReturnType(),
1292 else => unreachable,
1293 }
1405 const callee_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1406 return callee_ty.fnReturnTypeIp(ip);
12941407 },
12951408
12961409 .slice_elem_val, .ptr_elem_val, .array_elem_val => {
1297 const ptr_ty = air.typeOf(datas[inst].bin_op.lhs);
1298 return ptr_ty.elemType();
1410 const ptr_ty = air.typeOf(datas[inst].bin_op.lhs, ip);
1411 return ptr_ty.childTypeIp(ip);
12991412 },
13001413 .atomic_load => {
1301 const ptr_ty = air.typeOf(datas[inst].atomic_load.ptr);
1302 return ptr_ty.elemType();
1414 const ptr_ty = air.typeOf(datas[inst].atomic_load.ptr, ip);
1415 return ptr_ty.childTypeIp(ip);
13031416 },
13041417 .atomic_rmw => {
1305 const ptr_ty = air.typeOf(datas[inst].pl_op.operand);
1306 return ptr_ty.elemType();
1418 const ptr_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1419 return ptr_ty.childTypeIp(ip);
13071420 },
13081421
1309 .reduce, .reduce_optimized => return air.typeOf(datas[inst].reduce.operand).childType(),
1422 .reduce, .reduce_optimized => {
1423 const operand_ty = air.typeOf(datas[inst].reduce.operand, ip);
1424 return ip.indexToKey(operand_ty.ip_index).vector_type.child.toType();
1425 },
13101426
1311 .mul_add => return air.typeOf(datas[inst].pl_op.operand),
1427 .mul_add => return air.typeOf(datas[inst].pl_op.operand, ip),
13121428 .select => {
13131429 const extra = air.extraData(Air.Bin, datas[inst].pl_op.payload).data;
1314 return air.typeOf(extra.lhs);
1430 return air.typeOf(extra.lhs, ip);
13151431 },
13161432
13171433 .@"try" => {
1318 const err_union_ty = air.typeOf(datas[inst].pl_op.operand);
1319 return err_union_ty.errorUnionPayload();
1434 const err_union_ty = air.typeOf(datas[inst].pl_op.operand, ip);
1435 return ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type.toType();
13201436 },
13211437
13221438 .work_item_id,
13231439 .work_group_size,
13241440 .work_group_id,
13251441 => return Type.u32,
1442
1443 .inferred_alloc => unreachable,
1444 .inferred_alloc_comptime => unreachable,
13261445 }
13271446}
13281447
13291448pub fn getRefType(air: Air, ref: Air.Inst.Ref) Type {
13301449 const ref_int = @enumToInt(ref);
1331 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
1332 var buffer: Value.ToTypeBuffer = undefined;
1333 return Air.Inst.Ref.typed_value_map[ref_int].val.toType(&buffer);
1450 if (ref_int < ref_start_index) {
1451 const ip_index = @intToEnum(InternPool.Index, ref_int);
1452 return ip_index.toType();
13341453 }
1335 const inst_index = ref_int - Air.Inst.Ref.typed_value_map.len;
1454 const inst_index = ref_int - ref_start_index;
13361455 const air_tags = air.instructions.items(.tag);
13371456 const air_datas = air.instructions.items(.data);
1338 assert(air_tags[inst_index] == .const_ty);
1339 return air_datas[inst_index].ty;
1457 return switch (air_tags[inst_index]) {
1458 .interned => air_datas[inst_index].interned.toType(),
1459 else => unreachable,
1460 };
13401461}
13411462
13421463/// Returns the requested data, as well as the new index which is at the start of the
......@@ -1350,7 +1471,8 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end
13501471 u32 => air.extra[i],
13511472 Inst.Ref => @intToEnum(Inst.Ref, air.extra[i]),
13521473 i32 => @bitCast(i32, air.extra[i]),
1353 else => @compileError("bad field type"),
1474 InternPool.Index => @intToEnum(InternPool.Index, air.extra[i]),
1475 else => @compileError("bad field type: " ++ @typeName(field.type)),
13541476 };
13551477 i += 1;
13561478 }
......@@ -1363,17 +1485,17 @@ pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end
13631485pub fn deinit(air: *Air, gpa: std.mem.Allocator) void {
13641486 air.instructions.deinit(gpa);
13651487 gpa.free(air.extra);
1366 gpa.free(air.values);
13671488 air.* = undefined;
13681489}
13691490
1370const ref_start_index: u32 = Air.Inst.Ref.typed_value_map.len;
1491pub const ref_start_index: u32 = InternPool.static_len;
13711492
1372pub fn indexToRef(inst: Air.Inst.Index) Air.Inst.Ref {
1373 return @intToEnum(Air.Inst.Ref, ref_start_index + inst);
1493pub fn indexToRef(inst: Inst.Index) Inst.Ref {
1494 return @intToEnum(Inst.Ref, ref_start_index + inst);
13741495}
13751496
1376pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
1497pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
1498 assert(inst != .none);
13771499 const ref_int = @enumToInt(inst);
13781500 if (ref_int >= ref_start_index) {
13791501 return ref_int - ref_start_index;
......@@ -1382,18 +1504,23 @@ pub fn refToIndex(inst: Air.Inst.Ref) ?Air.Inst.Index {
13821504 }
13831505}
13841506
1507pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
1508 if (inst == .none) return null;
1509 return refToIndex(inst);
1510}
1511
13851512/// Returns `null` if runtime-known.
1386pub fn value(air: Air, inst: Air.Inst.Ref) ?Value {
1513pub fn value(air: Air, inst: Inst.Ref, mod: *Module) !?Value {
13871514 const ref_int = @enumToInt(inst);
1388 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
1389 return Air.Inst.Ref.typed_value_map[ref_int].val;
1515 if (ref_int < ref_start_index) {
1516 const ip_index = @intToEnum(InternPool.Index, ref_int);
1517 return ip_index.toValue();
13901518 }
1391 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
1519 const inst_index = @intCast(Air.Inst.Index, ref_int - ref_start_index);
13921520 const air_datas = air.instructions.items(.data);
13931521 switch (air.instructions.items(.tag)[inst_index]) {
1394 .constant => return air.values[air_datas[inst_index].ty_pl.payload],
1395 .const_ty => unreachable,
1396 else => return air.typeOfIndex(inst_index).onePossibleValue(),
1522 .interned => return air_datas[inst_index].interned.toValue(),
1523 else => return air.typeOfIndex(inst_index, &mod.intern_pool).onePossibleValue(mod),
13971524 }
13981525}
13991526
......@@ -1406,10 +1533,11 @@ pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
14061533 return bytes[0..end :0];
14071534}
14081535
1409/// Returns whether the given instruction must always be lowered, for instance because it can cause
1410/// side effects. If an instruction does not need to be lowered, and Liveness determines its result
1411/// is unused, backends should avoid lowering it.
1412pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
1536/// Returns whether the given instruction must always be lowered, for instance
1537/// because it can cause side effects. If an instruction does not need to be
1538/// lowered, and Liveness determines its result is unused, backends should
1539/// avoid lowering it.
1540pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
14131541 const data = air.instructions.items(.data)[inst];
14141542 return switch (air.instructions.items(.tag)[inst]) {
14151543 .arg,
......@@ -1498,6 +1626,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
14981626 .mul_with_overflow,
14991627 .shl_with_overflow,
15001628 .alloc,
1629 .inferred_alloc,
1630 .inferred_alloc_comptime,
15011631 .ret_ptr,
15021632 .bit_and,
15031633 .bit_or,
......@@ -1546,8 +1676,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
15461676 .cmp_neq_optimized,
15471677 .cmp_vector,
15481678 .cmp_vector_optimized,
1549 .constant,
1550 .const_ty,
1679 .interned,
15511680 .is_null,
15521681 .is_non_null,
15531682 .is_null_ptr,
......@@ -1616,8 +1745,8 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index) bool {
16161745 => false,
16171746
16181747 .assembly => @truncate(u1, air.extraData(Air.Asm, data.ty_pl.payload).data.flags >> 31) != 0,
1619 .load => air.typeOf(data.ty_op.operand).isVolatilePtr(),
1620 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs).isVolatilePtr(),
1621 .atomic_load => air.typeOf(data.atomic_load.ptr).isVolatilePtr(),
1748 .load => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip),
1749 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip),
1750 .atomic_load => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip),
16221751 };
16231752}
src/AstGen.zig+41-24
......@@ -3934,7 +3934,7 @@ fn fnDecl(
39343934 var section_gz = decl_gz.makeSubBlock(params_scope);
39353935 defer section_gz.unstack();
39363936 const section_ref: Zir.Inst.Ref = if (fn_proto.ast.section_expr == 0) .none else inst: {
3937 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .const_slice_u8_type } }, fn_proto.ast.section_expr);
3937 const inst = try expr(&decl_gz, params_scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, fn_proto.ast.section_expr);
39383938 if (section_gz.instructionsSlice().len == 0) {
39393939 // In this case we will send a len=0 body which can be encoded more efficiently.
39403940 break :inst inst;
......@@ -4137,7 +4137,7 @@ fn globalVarDecl(
41374137 break :inst try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .address_space_type } }, var_decl.ast.addrspace_node);
41384138 };
41394139 const section_inst: Zir.Inst.Ref = if (var_decl.ast.section_node == 0) .none else inst: {
4140 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .const_slice_u8_type } }, var_decl.ast.section_node);
4140 break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .slice_const_u8_type } }, var_decl.ast.section_node);
41414141 };
41424142 const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none;
41434143 wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace);
......@@ -4497,7 +4497,7 @@ fn testDecl(
44974497 .cc_gz = null,
44984498 .align_ref = .none,
44994499 .align_gz = null,
4500 .ret_ref = .void_type,
4500 .ret_ref = .anyerror_void_error_union_type,
45014501 .ret_gz = null,
45024502 .section_ref = .none,
45034503 .section_gz = null,
......@@ -4510,7 +4510,7 @@ fn testDecl(
45104510 .body_gz = &fn_block,
45114511 .lib_name = 0,
45124512 .is_var_args = false,
4513 .is_inferred_error = true,
4513 .is_inferred_error = false,
45144514 .is_test = true,
45154515 .is_extern = false,
45164516 .is_noinline = false,
......@@ -7878,7 +7878,7 @@ fn unionInit(
78787878 params: []const Ast.Node.Index,
78797879) InnerError!Zir.Inst.Ref {
78807880 const union_type = try typeExpr(gz, scope, params[0]);
7881 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
7881 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]);
78827882 const field_type = try gz.addPlNode(.field_type_ref, params[1], Zir.Inst.FieldTypeRef{
78837883 .container_type = union_type,
78847884 .field_name = field_name,
......@@ -8100,12 +8100,12 @@ fn builtinCall(
81008100 if (ri.rl == .ref) {
81018101 return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{
81028102 .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]),
8103 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
8103 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),
81048104 });
81058105 }
81068106 const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{
81078107 .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]),
8108 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]),
8108 .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]),
81098109 });
81108110 return rvalue(gz, ri, result, node);
81118111 },
......@@ -8271,11 +8271,11 @@ fn builtinCall(
82718271 .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of),
82728272
82738273 .ptr_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ptr_to_int),
8274 .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .compile_error),
8274 .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .compile_error),
82758275 .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota),
82768276 .enum_to_int => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .enum_to_int),
82778277 .bool_to_int => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .bool_to_int),
8278 .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .embed_file),
8278 .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .embed_file),
82798279 .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name),
82808280 .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety),
82818281 .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt),
......@@ -8334,7 +8334,7 @@ fn builtinCall(
83348334 },
83358335 .panic => {
83368336 try emitDbgNode(gz, node);
8337 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0], .panic);
8337 return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .panic);
83388338 },
83398339 .trap => {
83408340 try emitDbgNode(gz, node);
......@@ -8450,7 +8450,7 @@ fn builtinCall(
84508450 },
84518451 .c_define => {
84528452 if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{});
8453 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[0]);
8453 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0]);
84548454 const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]);
84558455 const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{
84568456 .node = gz.nodeIndexToRelative(node),
......@@ -8530,7 +8530,7 @@ fn builtinCall(
85308530 return rvalue(gz, ri, result, node);
85318531 },
85328532 .call => {
8533 const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .modifier_type } }, params[0]);
8533 const modifier = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .call_modifier_type } }, params[0]);
85348534 const callee = try expr(gz, scope, .{ .rl = .none }, params[1]);
85358535 const args = try expr(gz, scope, .{ .rl = .none }, params[2]);
85368536 const result = try gz.addPlNode(.builtin_call, node, Zir.Inst.BuiltinCall{
......@@ -8546,7 +8546,7 @@ fn builtinCall(
85468546 },
85478547 .field_parent_ptr => {
85488548 const parent_type = try typeExpr(gz, scope, params[0]);
8549 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, params[1]);
8549 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]);
85508550 const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{
85518551 .parent_type = parent_type,
85528552 .field_name = field_name,
......@@ -8701,7 +8701,7 @@ fn hasDeclOrField(
87018701 tag: Zir.Inst.Tag,
87028702) InnerError!Zir.Inst.Ref {
87038703 const container_type = try typeExpr(gz, scope, lhs_node);
8704 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node);
8704 const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, rhs_node);
87058705 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
87068706 .lhs = container_type,
87078707 .rhs = name,
......@@ -8851,7 +8851,7 @@ fn simpleCBuiltin(
88518851) InnerError!Zir.Inst.Ref {
88528852 const name: []const u8 = if (tag == .c_undef) "C undef" else "C include";
88538853 if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name});
8854 const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, operand_node);
8854 const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, operand_node);
88558855 _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{
88568856 .node = gz.nodeIndexToRelative(node),
88578857 .operand = operand,
......@@ -8869,7 +8869,7 @@ fn offsetOf(
88698869 tag: Zir.Inst.Tag,
88708870) InnerError!Zir.Inst.Ref {
88718871 const type_inst = try typeExpr(gz, scope, lhs_node);
8872 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .const_slice_u8_type } }, rhs_node);
8872 const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, rhs_node);
88738873 const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{
88748874 .lhs = type_inst,
88758875 .rhs = field_name,
......@@ -10271,6 +10271,8 @@ fn rvalue(
1027110271 as_ty | @enumToInt(Zir.Inst.Ref.i32_type),
1027210272 as_ty | @enumToInt(Zir.Inst.Ref.u64_type),
1027310273 as_ty | @enumToInt(Zir.Inst.Ref.i64_type),
10274 as_ty | @enumToInt(Zir.Inst.Ref.u128_type),
10275 as_ty | @enumToInt(Zir.Inst.Ref.i128_type),
1027410276 as_ty | @enumToInt(Zir.Inst.Ref.usize_type),
1027510277 as_ty | @enumToInt(Zir.Inst.Ref.isize_type),
1027610278 as_ty | @enumToInt(Zir.Inst.Ref.c_char_type),
......@@ -10296,15 +10298,30 @@ fn rvalue(
1029610298 as_ty | @enumToInt(Zir.Inst.Ref.comptime_int_type),
1029710299 as_ty | @enumToInt(Zir.Inst.Ref.comptime_float_type),
1029810300 as_ty | @enumToInt(Zir.Inst.Ref.noreturn_type),
10301 as_ty | @enumToInt(Zir.Inst.Ref.anyframe_type),
1029910302 as_ty | @enumToInt(Zir.Inst.Ref.null_type),
1030010303 as_ty | @enumToInt(Zir.Inst.Ref.undefined_type),
10301 as_ty | @enumToInt(Zir.Inst.Ref.fn_noreturn_no_args_type),
10302 as_ty | @enumToInt(Zir.Inst.Ref.fn_void_no_args_type),
10303 as_ty | @enumToInt(Zir.Inst.Ref.fn_naked_noreturn_no_args_type),
10304 as_ty | @enumToInt(Zir.Inst.Ref.fn_ccc_void_no_args_type),
10305 as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
10306 as_ty | @enumToInt(Zir.Inst.Ref.const_slice_u8_type),
1030710304 as_ty | @enumToInt(Zir.Inst.Ref.enum_literal_type),
10305 as_ty | @enumToInt(Zir.Inst.Ref.atomic_order_type),
10306 as_ty | @enumToInt(Zir.Inst.Ref.atomic_rmw_op_type),
10307 as_ty | @enumToInt(Zir.Inst.Ref.calling_convention_type),
10308 as_ty | @enumToInt(Zir.Inst.Ref.address_space_type),
10309 as_ty | @enumToInt(Zir.Inst.Ref.float_mode_type),
10310 as_ty | @enumToInt(Zir.Inst.Ref.reduce_op_type),
10311 as_ty | @enumToInt(Zir.Inst.Ref.call_modifier_type),
10312 as_ty | @enumToInt(Zir.Inst.Ref.prefetch_options_type),
10313 as_ty | @enumToInt(Zir.Inst.Ref.export_options_type),
10314 as_ty | @enumToInt(Zir.Inst.Ref.extern_options_type),
10315 as_ty | @enumToInt(Zir.Inst.Ref.type_info_type),
10316 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_u8_type),
10317 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_type),
10318 as_ty | @enumToInt(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type),
10319 as_ty | @enumToInt(Zir.Inst.Ref.single_const_pointer_to_comptime_int_type),
10320 as_ty | @enumToInt(Zir.Inst.Ref.slice_const_u8_type),
10321 as_ty | @enumToInt(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
10322 as_ty | @enumToInt(Zir.Inst.Ref.anyerror_void_error_union_type),
10323 as_ty | @enumToInt(Zir.Inst.Ref.generic_poison_type),
10324 as_ty | @enumToInt(Zir.Inst.Ref.empty_struct_type),
1030810325 as_comptime_int | @enumToInt(Zir.Inst.Ref.zero),
1030910326 as_comptime_int | @enumToInt(Zir.Inst.Ref.one),
1031010327 as_bool | @enumToInt(Zir.Inst.Ref.bool_true),
......@@ -10677,8 +10694,8 @@ fn identAsString(astgen: *AstGen, ident_token: Ast.TokenIndex) !u32 {
1067710694 const string_bytes = &astgen.string_bytes;
1067810695 const str_index = @intCast(u32, string_bytes.items.len);
1067910696 try astgen.appendIdentStr(ident_token, string_bytes);
10680 const key = string_bytes.items[str_index..];
10681 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, @as([]const u8, key), StringIndexAdapter{
10697 const key: []const u8 = string_bytes.items[str_index..];
10698 const gop = try astgen.string_table.getOrPutContextAdapted(gpa, key, StringIndexAdapter{
1068210699 .bytes = string_bytes,
1068310700 }, StringIndexContext{
1068410701 .bytes = string_bytes,
src/Autodoc.zig+23-24
......@@ -8,6 +8,7 @@ const CompilationModule = @import("Module.zig");
88const File = CompilationModule.File;
99const Module = @import("Package.zig");
1010const Tokenizer = std.zig.Tokenizer;
11const InternPool = @import("InternPool.zig");
1112const Zir = @import("Zir.zig");
1213const Ref = Zir.Inst.Ref;
1314const log = std.log.scoped(.autodoc);
......@@ -95,8 +96,6 @@ pub fn generateZirData(self: *Autodoc) !void {
9596 }
9697 }
9798
98 log.debug("Ref map size: {}", .{Ref.typed_value_map.len});
99
10099 const root_src_dir = self.comp_module.main_pkg.root_src_directory;
101100 const root_src_path = self.comp_module.main_pkg.root_src_path;
102101 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});
......@@ -108,18 +107,20 @@ pub fn generateZirData(self: *Autodoc) !void {
108107 const file = self.comp_module.import_table.get(abs_root_src_path).?; // file is expected to be present in the import table
109108 // Append all the types in Zir.Inst.Ref.
110109 {
111 try self.types.append(self.arena, .{
112 .ComptimeExpr = .{ .name = "ComptimeExpr" },
113 });
114
115 // this skips Ref.none but it's ok becuse we replaced it with ComptimeExpr
116 var i: u32 = 1;
117 while (i <= @enumToInt(Ref.anyerror_void_error_union_type)) : (i += 1) {
110 comptime std.debug.assert(@enumToInt(InternPool.Index.first_type) == 0);
111 var i: u32 = 0;
112 while (i <= @enumToInt(InternPool.Index.last_type)) : (i += 1) {
113 const ip_index = @intToEnum(InternPool.Index, i);
118114 var tmpbuf = std.ArrayList(u8).init(self.arena);
119 try Ref.typed_value_map[i].val.fmtDebug().format("", .{}, tmpbuf.writer());
115 if (ip_index == .generic_poison_type) {
116 // Not a real type, doesn't have a normal name
117 try tmpbuf.writer().writeAll("(generic poison)");
118 } else {
119 try ip_index.toType().fmt(self.comp_module).format("", .{}, tmpbuf.writer());
120 }
120121 try self.types.append(
121122 self.arena,
122 switch (@intToEnum(Ref, i)) {
123 switch (ip_index) {
123124 else => blk: {
124125 // TODO: map the remaining refs to a correct type
125126 // instead of just assinging "array" to them.
......@@ -1040,7 +1041,7 @@ fn walkInstruction(
10401041 .ret_load => {
10411042 const un_node = data[inst_index].un_node;
10421043 const res_ptr_ref = un_node.operand;
1043 const res_ptr_inst = @enumToInt(res_ptr_ref) - Ref.typed_value_map.len;
1044 const res_ptr_inst = Zir.refToIndex(res_ptr_ref).?;
10441045 // TODO: this instruction doesn't let us know trivially if there's
10451046 // branching involved or not. For now here's the strat:
10461047 // We search backwarts until `ret_ptr` for `store_node`,
......@@ -2157,11 +2158,10 @@ fn walkInstruction(
21572158 const lhs_ref = blk: {
21582159 var lhs_extra = extra;
21592160 while (true) {
2160 if (@enumToInt(lhs_extra.data.lhs) < Ref.typed_value_map.len) {
2161 const lhs = Zir.refToIndex(lhs_extra.data.lhs) orelse {
21612162 break :blk lhs_extra.data.lhs;
2162 }
2163 };
21632164
2164 const lhs = @enumToInt(lhs_extra.data.lhs) - Ref.typed_value_map.len;
21652165 if (tags[lhs] != .field_val and
21662166 tags[lhs] != .field_ptr and
21672167 tags[lhs] != .field_type) break :blk lhs_extra.data.lhs;
......@@ -2188,8 +2188,7 @@ fn walkInstruction(
21882188 // TODO: double check that we really don't need type info here
21892189
21902190 const wr = blk: {
2191 if (@enumToInt(lhs_ref) >= Ref.typed_value_map.len) {
2192 const lhs_inst = @enumToInt(lhs_ref) - Ref.typed_value_map.len;
2191 if (Zir.refToIndex(lhs_ref)) |lhs_inst| {
21932192 if (tags[lhs_inst] == .call or tags[lhs_inst] == .field_call) {
21942193 break :blk DocData.WalkResult{
21952194 .expr = .{
......@@ -4672,16 +4671,19 @@ fn walkRef(
46724671 ref: Ref,
46734672 need_type: bool, // true when the caller needs also a typeRef for the return value
46744673) AutodocErrors!DocData.WalkResult {
4675 const enum_value = @enumToInt(ref);
4676 if (enum_value <= @enumToInt(Ref.anyerror_void_error_union_type)) {
4674 if (ref == .none) {
4675 return .{ .expr = .{ .comptimeExpr = 0 } };
4676 } else if (@enumToInt(ref) <= @enumToInt(InternPool.Index.last_type)) {
46774677 // We can just return a type that indexes into `types` with the
46784678 // enum value because in the beginning we pre-filled `types` with
46794679 // the types that are listed in `Ref`.
46804680 return DocData.WalkResult{
46814681 .typeRef = .{ .type = @enumToInt(std.builtin.TypeId.Type) },
4682 .expr = .{ .type = enum_value },
4682 .expr = .{ .type = @enumToInt(ref) },
46834683 };
4684 } else if (enum_value < Ref.typed_value_map.len) {
4684 } else if (Zir.refToIndex(ref)) |zir_index| {
4685 return self.walkInstruction(file, parent_scope, parent_src, zir_index, need_type);
4686 } else {
46854687 switch (ref) {
46864688 else => {
46874689 panicWithContext(
......@@ -4774,9 +4776,6 @@ fn walkRef(
47744776 // } };
47754777 // },
47764778 }
4777 } else {
4778 const zir_index = enum_value - Ref.typed_value_map.len;
4779 return self.walkInstruction(file, parent_scope, parent_src, zir_index, need_type);
47804779 }
47814780}
47824781
src/Compilation.zig+38-26
......@@ -87,6 +87,7 @@ clang_preprocessor_mode: ClangPreprocessorMode,
8787/// Whether to print clang argvs to stdout.
8888verbose_cc: bool,
8989verbose_air: bool,
90verbose_intern_pool: bool,
9091verbose_llvm_ir: ?[]const u8,
9192verbose_llvm_bc: ?[]const u8,
9293verbose_cimport: bool,
......@@ -226,7 +227,7 @@ const Job = union(enum) {
226227 /// Write the constant value for a Decl to the output file.
227228 codegen_decl: Module.Decl.Index,
228229 /// Write the machine code for a function to the output file.
229 codegen_func: *Module.Fn,
230 codegen_func: Module.Fn.Index,
230231 /// Render the .h file snippet for the Decl.
231232 emit_h_decl: Module.Decl.Index,
232233 /// The Decl needs to be analyzed and possibly export itself.
......@@ -593,6 +594,7 @@ pub const InitOptions = struct {
593594 verbose_cc: bool = false,
594595 verbose_link: bool = false,
595596 verbose_air: bool = false,
597 verbose_intern_pool: bool = false,
596598 verbose_llvm_ir: ?[]const u8 = null,
597599 verbose_llvm_bc: ?[]const u8 = null,
598600 verbose_cimport: bool = false,
......@@ -1315,9 +1317,9 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
13151317 .global_zir_cache = global_zir_cache,
13161318 .local_zir_cache = local_zir_cache,
13171319 .emit_h = emit_h,
1318 .error_name_list = .{},
1320 .tmp_hack_arena = std.heap.ArenaAllocator.init(gpa),
13191321 };
1320 try module.error_name_list.append(gpa, "(no error)");
1322 try module.init();
13211323
13221324 break :blk module;
13231325 } else blk: {
......@@ -1574,6 +1576,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15741576 .clang_preprocessor_mode = options.clang_preprocessor_mode,
15751577 .verbose_cc = options.verbose_cc,
15761578 .verbose_air = options.verbose_air,
1579 .verbose_intern_pool = options.verbose_intern_pool,
15771580 .verbose_llvm_ir = options.verbose_llvm_ir,
15781581 .verbose_llvm_bc = options.verbose_llvm_bc,
15791582 .verbose_cimport = options.verbose_cimport,
......@@ -2026,6 +2029,13 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20262029 try comp.performAllTheWork(main_progress_node);
20272030
20282031 if (comp.bin_file.options.module) |module| {
2032 if (builtin.mode == .Debug and comp.verbose_intern_pool) {
2033 std.debug.print("intern pool stats for '{s}':\n", .{
2034 comp.bin_file.options.root_name,
2035 });
2036 module.intern_pool.dump();
2037 }
2038
20292039 if (comp.bin_file.options.is_test and comp.totalErrorCount() == 0) {
20302040 // The `test_functions` decl has been intentionally postponed until now,
20312041 // at which point we must populate it with the list of test functions that
......@@ -2042,7 +2052,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20422052 assert(decl.deletion_flag);
20432053 assert(decl.dependants.count() == 0);
20442054 const is_anon = if (decl.zir_decl_index == 0) blk: {
2045 break :blk decl.src_namespace.anon_decls.swapRemove(decl_index);
2055 break :blk module.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index);
20462056 } else false;
20472057
20482058 try module.clearDecl(decl_index, null);
......@@ -2523,8 +2533,7 @@ pub fn totalErrorCount(self: *Compilation) u32 {
25232533 // the previous parse success, including compile errors, but we cannot
25242534 // emit them until the file succeeds parsing.
25252535 for (module.failed_decls.keys()) |key| {
2526 const decl = module.declPtr(key);
2527 if (decl.getFileScope().okToReportErrors()) {
2536 if (module.declFileScope(key).okToReportErrors()) {
25282537 total += 1;
25292538 if (module.cimport_errors.get(key)) |errors| {
25302539 total += errors.len;
......@@ -2533,8 +2542,7 @@ pub fn totalErrorCount(self: *Compilation) u32 {
25332542 }
25342543 if (module.emit_h) |emit_h| {
25352544 for (emit_h.failed_decls.keys()) |key| {
2536 const decl = module.declPtr(key);
2537 if (decl.getFileScope().okToReportErrors()) {
2545 if (module.declFileScope(key).okToReportErrors()) {
25382546 total += 1;
25392547 }
25402548 }
......@@ -2618,7 +2626,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
26182626 var it = module.failed_files.iterator();
26192627 while (it.next()) |entry| {
26202628 if (entry.value_ptr.*) |msg| {
2621 try addModuleErrorMsg(&bundle, msg.*);
2629 try addModuleErrorMsg(module, &bundle, msg.*);
26222630 } else {
26232631 // Must be ZIR errors. Note that this may include AST errors.
26242632 // addZirErrorMessages asserts that the tree is loaded.
......@@ -2631,17 +2639,17 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
26312639 var it = module.failed_embed_files.iterator();
26322640 while (it.next()) |entry| {
26332641 const msg = entry.value_ptr.*;
2634 try addModuleErrorMsg(&bundle, msg.*);
2642 try addModuleErrorMsg(module, &bundle, msg.*);
26352643 }
26362644 }
26372645 {
26382646 var it = module.failed_decls.iterator();
26392647 while (it.next()) |entry| {
2640 const decl = module.declPtr(entry.key_ptr.*);
2648 const decl_index = entry.key_ptr.*;
26412649 // Skip errors for Decls within files that had a parse failure.
26422650 // We'll try again once parsing succeeds.
2643 if (decl.getFileScope().okToReportErrors()) {
2644 try addModuleErrorMsg(&bundle, entry.value_ptr.*.*);
2651 if (module.declFileScope(decl_index).okToReportErrors()) {
2652 try addModuleErrorMsg(module, &bundle, entry.value_ptr.*.*);
26452653 if (module.cimport_errors.get(entry.key_ptr.*)) |cimport_errors| for (cimport_errors) |c_error| {
26462654 try bundle.addRootErrorMessage(.{
26472655 .msg = try bundle.addString(std.mem.span(c_error.msg)),
......@@ -2662,16 +2670,16 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
26622670 if (module.emit_h) |emit_h| {
26632671 var it = emit_h.failed_decls.iterator();
26642672 while (it.next()) |entry| {
2665 const decl = module.declPtr(entry.key_ptr.*);
2673 const decl_index = entry.key_ptr.*;
26662674 // Skip errors for Decls within files that had a parse failure.
26672675 // We'll try again once parsing succeeds.
2668 if (decl.getFileScope().okToReportErrors()) {
2669 try addModuleErrorMsg(&bundle, entry.value_ptr.*.*);
2676 if (module.declFileScope(decl_index).okToReportErrors()) {
2677 try addModuleErrorMsg(module, &bundle, entry.value_ptr.*.*);
26702678 }
26712679 }
26722680 }
26732681 for (module.failed_exports.values()) |value| {
2674 try addModuleErrorMsg(&bundle, value.*);
2682 try addModuleErrorMsg(module, &bundle, value.*);
26752683 }
26762684 }
26772685
......@@ -2703,7 +2711,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
27032711 const values = module.compile_log_decls.values();
27042712 // First one will be the error; subsequent ones will be notes.
27052713 const err_decl = module.declPtr(keys[0]);
2706 const src_loc = err_decl.nodeOffsetSrcLoc(values[0]);
2714 const src_loc = err_decl.nodeOffsetSrcLoc(values[0], module);
27072715 const err_msg = Module.ErrorMsg{
27082716 .src_loc = src_loc,
27092717 .msg = "found compile log statement",
......@@ -2714,12 +2722,12 @@ pub fn getAllErrorsAlloc(self: *Compilation) !ErrorBundle {
27142722 for (keys[1..], 0..) |key, i| {
27152723 const note_decl = module.declPtr(key);
27162724 err_msg.notes[i] = .{
2717 .src_loc = note_decl.nodeOffsetSrcLoc(values[i + 1]),
2725 .src_loc = note_decl.nodeOffsetSrcLoc(values[i + 1], module),
27182726 .msg = "also here",
27192727 };
27202728 }
27212729
2722 try addModuleErrorMsg(&bundle, err_msg);
2730 try addModuleErrorMsg(module, &bundle, err_msg);
27232731 }
27242732 }
27252733
......@@ -2775,8 +2783,9 @@ pub const ErrorNoteHashContext = struct {
27752783 }
27762784};
27772785
2778pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg) !void {
2786pub fn addModuleErrorMsg(mod: *Module, eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg) !void {
27792787 const gpa = eb.gpa;
2788 const ip = &mod.intern_pool;
27802789 const err_source = module_err_msg.src_loc.file_scope.getSource(gpa) catch |err| {
27812790 const file_path = try module_err_msg.src_loc.file_scope.fullPath(gpa);
27822791 defer gpa.free(file_path);
......@@ -2802,7 +2811,7 @@ pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg)
28022811 .src_loc = .none,
28032812 });
28042813 break;
2805 } else if (module_reference.decl == null) {
2814 } else if (module_reference.decl == .none) {
28062815 try ref_traces.append(gpa, .{
28072816 .decl_name = 0,
28082817 .src_loc = .none,
......@@ -2815,7 +2824,7 @@ pub fn addModuleErrorMsg(eb: *ErrorBundle.Wip, module_err_msg: Module.ErrorMsg)
28152824 const rt_file_path = try module_reference.src_loc.file_scope.fullPath(gpa);
28162825 defer gpa.free(rt_file_path);
28172826 try ref_traces.append(gpa, .{
2818 .decl_name = try eb.addString(std.mem.sliceTo(module_reference.decl.?, 0)),
2827 .decl_name = try eb.addString(ip.stringToSliceUnwrap(module_reference.decl).?),
28192828 .src_loc = try eb.addSourceLocation(.{
28202829 .src_path = try eb.addString(rt_file_path),
28212830 .span_start = span.start,
......@@ -3204,7 +3213,8 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
32043213 // Tests are always emitted in test binaries. The decl_refs are created by
32053214 // Module.populateTestFunctions, but this will not queue body analysis, so do
32063215 // that now.
3207 try module.ensureFuncBodyAnalysisQueued(decl.val.castTag(.function).?.data);
3216 const func_index = module.intern_pool.indexToFunc(decl.val.ip_index).unwrap().?;
3217 try module.ensureFuncBodyAnalysisQueued(func_index);
32083218 }
32093219 },
32103220 .update_embed_file => |embed_file| {
......@@ -3228,7 +3238,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
32283238 try module.failed_decls.ensureUnusedCapacity(gpa, 1);
32293239 module.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
32303240 gpa,
3231 decl.srcLoc(),
3241 decl.srcLoc(module),
32323242 "unable to update line number: {s}",
32333243 .{@errorName(err)},
32343244 ));
......@@ -3841,7 +3851,7 @@ fn reportRetryableEmbedFileError(
38413851 const mod = comp.bin_file.options.module.?;
38423852 const gpa = mod.gpa;
38433853
3844 const src_loc: Module.SrcLoc = mod.declPtr(embed_file.owner_decl).srcLoc();
3854 const src_loc: Module.SrcLoc = mod.declPtr(embed_file.owner_decl).srcLoc(mod);
38453855
38463856 const err_msg = if (embed_file.pkg.root_src_directory.path) |dir_path|
38473857 try Module.ErrorMsg.create(
......@@ -5417,6 +5427,7 @@ fn buildOutputFromZig(
54175427 .verbose_cc = comp.verbose_cc,
54185428 .verbose_link = comp.bin_file.options.verbose_link,
54195429 .verbose_air = comp.verbose_air,
5430 .verbose_intern_pool = comp.verbose_intern_pool,
54205431 .verbose_llvm_ir = comp.verbose_llvm_ir,
54215432 .verbose_llvm_bc = comp.verbose_llvm_bc,
54225433 .verbose_cimport = comp.verbose_cimport,
......@@ -5495,6 +5506,7 @@ pub fn build_crt_file(
54955506 .verbose_cc = comp.verbose_cc,
54965507 .verbose_link = comp.bin_file.options.verbose_link,
54975508 .verbose_air = comp.verbose_air,
5509 .verbose_intern_pool = comp.verbose_intern_pool,
54985510 .verbose_llvm_ir = comp.verbose_llvm_ir,
54995511 .verbose_llvm_bc = comp.verbose_llvm_bc,
55005512 .verbose_cimport = comp.verbose_cimport,
src/InternPool.zig+5742-266
......@@ -1,316 +1,5792 @@
1//! All interned objects have both a value and a type.
2//! This data structure is self-contained, with the following exceptions:
3//! * type_struct via Module.Struct.Index
4//! * type_opaque via Module.Namespace.Index and Module.Decl.Index
5
6/// Maps `Key` to `Index`. `Key` objects are not stored anywhere; they are
7/// constructed lazily.
18map: std.AutoArrayHashMapUnmanaged(void, void) = .{},
29items: std.MultiArrayList(Item) = .{},
310extra: std.ArrayListUnmanaged(u32) = .{},
11/// On 32-bit systems, this array is ignored and extra is used for everything.
12/// On 64-bit systems, this array is used for big integers and associated metadata.
13/// Use the helper methods instead of accessing this directly in order to not
14/// violate the above mechanism.
15limbs: std.ArrayListUnmanaged(u64) = .{},
16/// In order to store references to strings in fewer bytes, we copy all
17/// string bytes into here. String bytes can be null. It is up to whomever
18/// is referencing the data here whether they want to store both index and length,
19/// thus allowing null bytes, or store only index, and use null-termination. The
20/// `string_bytes` array is agnostic to either usage.
21string_bytes: std.ArrayListUnmanaged(u8) = .{},
422
5const InternPool = @This();
23/// Struct objects are stored in this data structure because:
24/// * They contain pointers such as the field maps.
25/// * They need to be mutated after creation.
26allocated_structs: std.SegmentedList(Module.Struct, 0) = .{},
27/// When a Struct object is freed from `allocated_structs`, it is pushed into this stack.
28structs_free_list: std.ArrayListUnmanaged(Module.Struct.Index) = .{},
29
30/// Union objects are stored in this data structure because:
31/// * They contain pointers such as the field maps.
32/// * They need to be mutated after creation.
33allocated_unions: std.SegmentedList(Module.Union, 0) = .{},
34/// When a Union object is freed from `allocated_unions`, it is pushed into this stack.
35unions_free_list: std.ArrayListUnmanaged(Module.Union.Index) = .{},
36
37/// Fn objects are stored in this data structure because:
38/// * They need to be mutated after creation.
39allocated_funcs: std.SegmentedList(Module.Fn, 0) = .{},
40/// When a Fn object is freed from `allocated_funcs`, it is pushed into this stack.
41funcs_free_list: std.ArrayListUnmanaged(Module.Fn.Index) = .{},
42
43/// InferredErrorSet objects are stored in this data structure because:
44/// * They contain pointers such as the errors map and the set of other inferred error sets.
45/// * They need to be mutated after creation.
46allocated_inferred_error_sets: std.SegmentedList(Module.Fn.InferredErrorSet, 0) = .{},
47/// When a Struct object is freed from `allocated_inferred_error_sets`, it is
48/// pushed into this stack.
49inferred_error_sets_free_list: std.ArrayListUnmanaged(Module.Fn.InferredErrorSet.Index) = .{},
50
51/// Some types such as enums, structs, and unions need to store mappings from field names
52/// to field index, or value to field index. In such cases, they will store the underlying
53/// field names and values directly, relying on one of these maps, stored separately,
54/// to provide lookup.
55maps: std.ArrayListUnmanaged(std.AutoArrayHashMapUnmanaged(void, void)) = .{},
56
57/// Used for finding the index inside `string_bytes`.
58string_table: std.HashMapUnmanaged(
59 u32,
60 void,
61 std.hash_map.StringIndexContext,
62 std.hash_map.default_max_load_percentage,
63) = .{},
64
65const builtin = @import("builtin");
666const std = @import("std");
767const Allocator = std.mem.Allocator;
868const assert = std.debug.assert;
69const BigIntConst = std.math.big.int.Const;
70const BigIntMutable = std.math.big.int.Mutable;
71const Limb = std.math.big.Limb;
72const Hash = std.hash.Wyhash;
73
74const InternPool = @This();
75const Module = @import("Module.zig");
76const Sema = @import("Sema.zig");
977
1078const KeyAdapter = struct {
1179 intern_pool: *const InternPool,
1280
1381 pub fn eql(ctx: @This(), a: Key, b_void: void, b_map_index: usize) bool {
1482 _ = b_void;
15 return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a);
83 return ctx.intern_pool.indexToKey(@intToEnum(Index, b_map_index)).eql(a, ctx.intern_pool);
1684 }
1785
1886 pub fn hash(ctx: @This(), a: Key) u32 {
19 _ = ctx;
20 return a.hash();
87 return a.hash32(ctx.intern_pool);
2188 }
2289};
2390
24pub const Key = union(enum) {
25 int_type: struct {
26 signedness: std.builtin.Signedness,
27 bits: u16,
28 },
29 ptr_type: struct {
30 elem_type: Index,
31 sentinel: Index,
32 alignment: u16,
33 size: std.builtin.Type.Pointer.Size,
34 is_const: bool,
35 is_volatile: bool,
36 is_allowzero: bool,
37 address_space: std.builtin.AddressSpace,
38 },
39 array_type: struct {
40 len: u64,
41 child: Index,
42 sentinel: Index,
43 },
44 vector_type: struct {
45 len: u32,
46 child: Index,
47 },
48 optional_type: struct {
49 payload_type: Index,
50 },
51 error_union_type: struct {
52 error_set_type: Index,
53 payload_type: Index,
54 },
55 simple: Simple,
91/// An index into `maps` which might be `none`.
92pub const OptionalMapIndex = enum(u32) {
93 none = std.math.maxInt(u32),
94 _,
5695
57 pub fn hash(key: Key) u32 {
58 var hasher = std.hash.Wyhash.init(0);
59 switch (key) {
60 .int_type => |int_type| {
61 std.hash.autoHash(&hasher, int_type);
62 },
63 .array_type => |array_type| {
64 std.hash.autoHash(&hasher, array_type);
65 },
66 else => @panic("TODO"),
67 }
68 return @truncate(u32, hasher.final());
96 pub fn unwrap(oi: OptionalMapIndex) ?MapIndex {
97 if (oi == .none) return null;
98 return @intToEnum(MapIndex, @enumToInt(oi));
6999 }
100};
70101
71 pub fn eql(a: Key, b: Key) bool {
72 const KeyTag = std.meta.Tag(Key);
73 const a_tag: KeyTag = a;
74 const b_tag: KeyTag = b;
75 if (a_tag != b_tag) return false;
76 switch (a) {
77 .int_type => |a_info| {
78 const b_info = b.int_type;
79 return std.meta.eql(a_info, b_info);
80 },
81 .array_type => |a_info| {
82 const b_info = b.array_type;
83 return std.meta.eql(a_info, b_info);
84 },
85 else => @panic("TODO"),
86 }
102/// An index into `maps`.
103pub const MapIndex = enum(u32) {
104 _,
105
106 pub fn toOptional(i: MapIndex) OptionalMapIndex {
107 return @intToEnum(OptionalMapIndex, @enumToInt(i));
87108 }
88109};
89110
90pub const Item = struct {
91 tag: Tag,
92 /// The doc comments on the respective Tag explain how to interpret this.
93 data: u32,
111pub const RuntimeIndex = enum(u32) {
112 zero = 0,
113 comptime_field_ptr = std.math.maxInt(u32),
114 _,
115
116 pub fn increment(ri: *RuntimeIndex) void {
117 ri.* = @intToEnum(RuntimeIndex, @enumToInt(ri.*) + 1);
118 }
94119};
95120
96/// Represents an index into `map`. It represents the canonical index
97/// of a `Value` within this `InternPool`. The values are typed.
98/// Two values which have the same type can be equality compared simply
99/// by checking if their indexes are equal, provided they are both in
100/// the same `InternPool`.
101pub const Index = enum(u32) {
102 none = std.math.maxInt(u32),
121/// An index into `string_bytes`.
122pub const String = enum(u32) {
103123 _,
104124};
105125
106pub const Tag = enum(u8) {
107 /// An integer type.
108 /// data is number of bits
109 type_int_signed,
110 /// An integer type.
111 /// data is number of bits
112 type_int_unsigned,
113 /// An array type.
114 /// data is payload to Array.
115 type_array,
116 /// A type or value that can be represented with only an enum tag.
117 /// data is Simple enum value
118 simple,
119 /// An unsigned integer value that can be represented by u32.
120 /// data is integer value
121 int_u32,
122 /// An unsigned integer value that can be represented by i32.
123 /// data is integer value bitcasted to u32.
124 int_i32,
125 /// A positive integer value that does not fit in 32 bits.
126 /// data is a extra index to BigInt.
127 int_big_positive,
128 /// A negative integer value that does not fit in 32 bits.
129 /// data is a extra index to BigInt.
130 int_big_negative,
131 /// A float value that can be represented by f32.
132 /// data is float value bitcasted to u32.
133 float_f32,
134 /// A float value that can be represented by f64.
135 /// data is payload index to Float64.
136 float_f64,
137 /// A float value that can be represented by f128.
138 /// data is payload index to Float128.
139 float_f128,
140};
126/// An index into `string_bytes`.
127pub const NullTerminatedString = enum(u32) {
128 /// This is distinct from `none` - it is a valid index that represents empty string.
129 empty = 0,
130 _,
141131
142pub const Simple = enum(u32) {
143 f16,
144 f32,
145 f64,
146 f80,
147 f128,
148 usize,
149 isize,
150 c_short,
151 c_ushort,
152 c_int,
153 c_uint,
154 c_long,
155 c_ulong,
156 c_longlong,
157 c_ulonglong,
158 c_longdouble,
159 anyopaque,
160 bool,
161 void,
162 type,
163 anyerror,
164 comptime_int,
165 comptime_float,
166 noreturn,
167 @"anyframe",
168 null_type,
169 undefined_type,
170 enum_literal_type,
171 undefined,
172 void_value,
173 null,
174 bool_true,
175 bool_false,
176};
132 pub fn toString(self: NullTerminatedString) String {
133 return @intToEnum(String, @enumToInt(self));
134 }
177135
178pub const Array = struct {
179 len: u32,
180 child: Index,
181};
136 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString {
137 return @intToEnum(OptionalNullTerminatedString, @enumToInt(self));
138 }
182139
183pub fn deinit(ip: *InternPool, gpa: Allocator) void {
184 ip.map.deinit(gpa);
185 ip.items.deinit(gpa);
186 ip.extra.deinit(gpa);
187}
140 const Adapter = struct {
141 strings: []const NullTerminatedString,
188142
189pub fn indexToKey(ip: InternPool, index: Index) Key {
190 const item = ip.items.get(@enumToInt(index));
191 const data = item.data;
192 return switch (item.tag) {
193 .type_int_signed => .{
194 .int_type = .{
195 .signedness = .signed,
196 .bits = @intCast(u16, data),
197 },
198 },
199 .type_int_unsigned => .{
200 .int_type = .{
201 .signedness = .unsigned,
202 .bits = @intCast(u16, data),
203 },
204 },
205 .type_array => {
206 const array_info = ip.extraData(Array, data);
207 return .{ .array_type = .{
208 .len = array_info.len,
209 .child = array_info.child,
210 .sentinel = .none,
211 } };
212 },
213 .simple => .{ .simple = @intToEnum(Simple, data) },
143 pub fn eql(ctx: @This(), a: NullTerminatedString, b_void: void, b_map_index: usize) bool {
144 _ = b_void;
145 return a == ctx.strings[b_map_index];
146 }
214147
215 else => @panic("TODO"),
148 pub fn hash(ctx: @This(), a: NullTerminatedString) u32 {
149 _ = ctx;
150 return std.hash.uint32(@enumToInt(a));
151 }
216152 };
217}
218153
219pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
220 const adapter: KeyAdapter = .{ .intern_pool = ip };
221 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
222 if (gop.found_existing) {
223 return @intToEnum(Index, gop.index);
154 /// Compare based on integer value alone, ignoring the string contents.
155 pub fn indexLessThan(ctx: void, a: NullTerminatedString, b: NullTerminatedString) bool {
156 _ = ctx;
157 return @enumToInt(a) < @enumToInt(b);
224158 }
225 switch (key) {
226 .int_type => |int_type| {
227 const tag: Tag = switch (int_type.signedness) {
228 .signed => .type_int_signed,
229 .unsigned => .type_int_unsigned,
230 };
231 try ip.items.append(gpa, .{
232 .tag = tag,
233 .data = int_type.bits,
234 });
235 },
236 .array_type => |array_type| {
237 const len = @intCast(u32, array_type.len); // TODO have a big_array encoding
238 assert(array_type.sentinel == .none); // TODO have a sentinel_array encoding
239 try ip.items.append(gpa, .{
240 .tag = .type_array,
241 .data = try ip.addExtra(gpa, Array{
242 .len = len,
243 .child = array_type.child,
244 }),
245 });
246 },
247 else => @panic("TODO"),
159
160 pub fn toUnsigned(self: NullTerminatedString, ip: *const InternPool) ?u32 {
161 const s = ip.stringToSlice(self);
162 if (s.len > 1 and s[0] == '0') return null;
163 if (std.mem.indexOfScalar(u8, s, '_')) |_| return null;
164 return std.fmt.parseUnsigned(u32, s, 10) catch null;
248165 }
249 return @intToEnum(Index, ip.items.len - 1);
250}
251166
252fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
253 const fields = std.meta.fields(@TypeOf(extra));
254 try ip.extra.ensureUnusedCapacity(gpa, fields.len);
255 return ip.addExtraAssumeCapacity(extra);
256}
167 const FormatData = struct {
168 string: NullTerminatedString,
169 ip: *const InternPool,
170 };
171 fn format(
172 data: FormatData,
173 comptime specifier: []const u8,
174 _: std.fmt.FormatOptions,
175 writer: anytype,
176 ) @TypeOf(writer).Error!void {
177 const s = data.ip.stringToSlice(data.string);
178 if (comptime std.mem.eql(u8, specifier, "")) {
179 try writer.writeAll(s);
180 } else if (comptime std.mem.eql(u8, specifier, "i")) {
181 try writer.print("{}", .{std.zig.fmtId(s)});
182 } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");
183 }
257184
258fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
259 const fields = std.meta.fields(@TypeOf(extra));
260 const result = @intCast(u32, ip.extra.items.len);
261 inline for (fields) |field| {
262 ip.extra.appendAssumeCapacity(switch (field.type) {
263 u32 => @field(extra, field.name),
264 Index => @enumToInt(@field(extra, field.name)),
265 i32 => @bitCast(u32, @field(extra, field.name)),
266 else => @compileError("bad field type"),
267 });
185 pub fn fmt(self: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(format) {
186 return .{ .data = .{ .string = self, .ip = ip } };
268187 }
269 return result;
270}
188};
271189
272fn extraData(ip: InternPool, comptime T: type, index: usize) T {
273 const fields = std.meta.fields(T);
274 var i: usize = index;
275 var result: T = undefined;
276 inline for (fields) |field| {
277 @field(result, field.name) = switch (field.type) {
278 u32 => ip.extra.items[i],
279 Index => @intToEnum(Index, ip.extra.items[i]),
280 i32 => @bitCast(i32, ip.extra.items[i]),
281 else => @compileError("bad field type"),
282 };
283 i += 1;
190/// An index into `string_bytes` which might be `none`.
191pub const OptionalNullTerminatedString = enum(u32) {
192 /// This is distinct from `none` - it is a valid index that represents empty string.
193 empty = 0,
194 none = std.math.maxInt(u32),
195 _,
196
197 pub fn unwrap(oi: OptionalNullTerminatedString) ?NullTerminatedString {
198 if (oi == .none) return null;
199 return @intToEnum(NullTerminatedString, @enumToInt(oi));
284200 }
285 return result;
286}
201};
287202
288test "basic usage" {
289 const gpa = std.testing.allocator;
203pub const Key = union(enum) {
204 int_type: IntType,
205 ptr_type: PtrType,
206 array_type: ArrayType,
207 vector_type: VectorType,
208 opt_type: Index,
209 /// `anyframe->T`. The payload is the child type, which may be `none` to indicate
210 /// `anyframe`.
211 anyframe_type: Index,
212 error_union_type: ErrorUnionType,
213 simple_type: SimpleType,
214 /// This represents a struct that has been explicitly declared in source code,
215 /// or was created with `@Type`. It is unique and based on a declaration.
216 /// It may be a tuple, if declared like this: `struct {A, B, C}`.
217 struct_type: StructType,
218 /// This is an anonymous struct or tuple type which has no corresponding
219 /// declaration. It is used for types that have no `struct` keyword in the
220 /// source code, and were not created via `@Type`.
221 anon_struct_type: AnonStructType,
222 union_type: UnionType,
223 opaque_type: OpaqueType,
224 enum_type: EnumType,
225 func_type: FuncType,
226 error_set_type: ErrorSetType,
227 inferred_error_set_type: Module.Fn.InferredErrorSet.Index,
290228
291 var ip: InternPool = .{};
292 defer ip.deinit(gpa);
229 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented
230 /// via `simple_value` and has a named `Index` tag for it.
231 undef: Index,
232 runtime_value: TypeValue,
233 simple_value: SimpleValue,
234 variable: Variable,
235 extern_func: ExternFunc,
236 func: Func,
237 int: Key.Int,
238 err: Error,
239 error_union: ErrorUnion,
240 enum_literal: NullTerminatedString,
241 /// A specific enum tag, indicated by the integer tag value.
242 enum_tag: EnumTag,
243 /// An empty enum or union. TODO: this value's existence is strange, because such a type in
244 /// reality has no values. See #15909.
245 /// Payload is the type for which we are an empty value.
246 empty_enum_value: Index,
247 float: Float,
248 ptr: Ptr,
249 opt: Opt,
250 /// An instance of a struct, array, or vector.
251 /// Each element/field stored as an `Index`.
252 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
253 /// so the slice length will be one more than the type's array length.
254 aggregate: Aggregate,
255 /// An instance of a union.
256 un: Union,
293257
294 const i32_type = try ip.get(gpa, .{ .int_type = .{
295 .signedness = .signed,
296 .bits = 32,
297 } });
298 const array_i32 = try ip.get(gpa, .{ .array_type = .{
299 .len = 10,
300 .child = i32_type,
301 .sentinel = .none,
302 } });
258 /// A comptime function call with a memoized result.
259 memoized_call: Key.MemoizedCall,
303260
304 const another_i32_type = try ip.get(gpa, .{ .int_type = .{
305 .signedness = .signed,
306 .bits = 32,
307 } });
308 try std.testing.expect(another_i32_type == i32_type);
261 pub const TypeValue = extern struct {
262 ty: Index,
263 val: Index,
264 };
309265
310 const another_array_i32 = try ip.get(gpa, .{ .array_type = .{
311 .len = 10,
312 .child = i32_type,
313 .sentinel = .none,
314 } });
315 try std.testing.expect(another_array_i32 == array_i32);
266 pub const IntType = std.builtin.Type.Int;
267
268 /// Extern for hashing via memory reinterpretation.
269 pub const ErrorUnionType = extern struct {
270 error_set_type: Index,
271 payload_type: Index,
272 };
273
274 pub const ErrorSetType = struct {
275 /// Set of error names, sorted by null terminated string index.
276 names: []const NullTerminatedString,
277 /// This is ignored by `get` but will always be provided by `indexToKey`.
278 names_map: OptionalMapIndex = .none,
279
280 /// Look up field index based on field name.
281 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
282 const map = &ip.maps.items[@enumToInt(self.names_map.unwrap().?)];
283 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names };
284 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
285 return @intCast(u32, field_index);
286 }
287 };
288
289 /// Extern layout so it can be hashed with `std.mem.asBytes`.
290 pub const PtrType = extern struct {
291 child: Index,
292 sentinel: Index = .none,
293 flags: Flags = .{},
294 packed_offset: PackedOffset = .{ .bit_offset = 0, .host_size = 0 },
295
296 pub const VectorIndex = enum(u16) {
297 none = std.math.maxInt(u16),
298 runtime = std.math.maxInt(u16) - 1,
299 _,
300 };
301
302 pub const Flags = packed struct(u32) {
303 size: Size = .One,
304 /// `none` indicates the ABI alignment of the pointee_type. In this
305 /// case, this field *must* be set to `none`, otherwise the
306 /// `InternPool` equality and hashing functions will return incorrect
307 /// results.
308 alignment: Alignment = .none,
309 is_const: bool = false,
310 is_volatile: bool = false,
311 is_allowzero: bool = false,
312 /// See src/target.zig defaultAddressSpace function for how to obtain
313 /// an appropriate value for this field.
314 address_space: AddressSpace = .generic,
315 vector_index: VectorIndex = .none,
316 };
317
318 pub const PackedOffset = packed struct(u32) {
319 /// If this is non-zero it means the pointer points to a sub-byte
320 /// range of data, which is backed by a "host integer" with this
321 /// number of bytes.
322 /// When host_size=pointee_abi_size and bit_offset=0, this must be
323 /// represented with host_size=0 instead.
324 host_size: u16,
325 bit_offset: u16,
326 };
327
328 pub const Size = std.builtin.Type.Pointer.Size;
329 pub const AddressSpace = std.builtin.AddressSpace;
330 };
331
332 /// Extern so that hashing can be done via memory reinterpreting.
333 pub const ArrayType = extern struct {
334 len: u64,
335 child: Index,
336 sentinel: Index = .none,
337 };
338
339 /// Extern so that hashing can be done via memory reinterpreting.
340 pub const VectorType = extern struct {
341 len: u32,
342 child: Index,
343 };
344
345 pub const OpaqueType = extern struct {
346 /// The Decl that corresponds to the opaque itself.
347 decl: Module.Decl.Index,
348 /// Represents the declarations inside this opaque.
349 namespace: Module.Namespace.Index,
350 };
351
352 pub const StructType = extern struct {
353 /// The `none` tag is used to represent a struct with no fields.
354 index: Module.Struct.OptionalIndex,
355 /// May be `none` if the struct has no declarations.
356 namespace: Module.Namespace.OptionalIndex,
357 };
358
359 pub const AnonStructType = struct {
360 types: []const Index,
361 /// This may be empty, indicating this is a tuple.
362 names: []const NullTerminatedString,
363 /// These elements may be `none`, indicating runtime-known.
364 values: []const Index,
365
366 pub fn isTuple(self: AnonStructType) bool {
367 return self.names.len == 0;
368 }
369 };
370
371 pub const UnionType = struct {
372 index: Module.Union.Index,
373 runtime_tag: RuntimeTag,
374
375 pub const RuntimeTag = enum { none, safety, tagged };
376
377 pub fn hasTag(self: UnionType) bool {
378 return switch (self.runtime_tag) {
379 .none => false,
380 .tagged, .safety => true,
381 };
382 }
383 };
384
385 pub const EnumType = struct {
386 /// The Decl that corresponds to the enum itself.
387 decl: Module.Decl.Index,
388 /// Represents the declarations inside this enum.
389 namespace: Module.Namespace.OptionalIndex,
390 /// An integer type which is used for the numerical value of the enum.
391 /// This field is present regardless of whether the enum has an
392 /// explicitly provided tag type or auto-numbered.
393 tag_ty: Index,
394 /// Set of field names in declaration order.
395 names: []const NullTerminatedString,
396 /// Maps integer tag value to field index.
397 /// Entries are in declaration order, same as `fields`.
398 /// If this is empty, it means the enum tags are auto-numbered.
399 values: []const Index,
400 tag_mode: TagMode,
401 /// This is ignored by `get` but will always be provided by `indexToKey`.
402 names_map: OptionalMapIndex = .none,
403 /// This is ignored by `get` but will be provided by `indexToKey` when
404 /// a value map exists.
405 values_map: OptionalMapIndex = .none,
406
407 pub const TagMode = enum {
408 /// The integer tag type was auto-numbered by zig.
409 auto,
410 /// The integer tag type was provided by the enum declaration, and the enum
411 /// is exhaustive.
412 explicit,
413 /// The integer tag type was provided by the enum declaration, and the enum
414 /// is non-exhaustive.
415 nonexhaustive,
416 };
417
418 /// Look up field index based on field name.
419 pub fn nameIndex(self: EnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 {
420 const map = &ip.maps.items[@enumToInt(self.names_map.unwrap().?)];
421 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names };
422 const field_index = map.getIndexAdapted(name, adapter) orelse return null;
423 return @intCast(u32, field_index);
424 }
425
426 /// Look up field index based on tag value.
427 /// Asserts that `values_map` is not `none`.
428 /// This function returns `null` when `tag_val` does not have the
429 /// integer tag type of the enum.
430 pub fn tagValueIndex(self: EnumType, ip: *const InternPool, tag_val: Index) ?u32 {
431 assert(tag_val != .none);
432 // TODO: we should probably decide a single interface for this function, but currently
433 // it's being called with both tag values and underlying ints. Fix this!
434 const int_tag_val = switch (ip.indexToKey(tag_val)) {
435 .enum_tag => |enum_tag| enum_tag.int,
436 .int => tag_val,
437 else => unreachable,
438 };
439 if (self.values_map.unwrap()) |values_map| {
440 const map = &ip.maps.items[@enumToInt(values_map)];
441 const adapter: Index.Adapter = .{ .indexes = self.values };
442 const field_index = map.getIndexAdapted(int_tag_val, adapter) orelse return null;
443 return @intCast(u32, field_index);
444 }
445 // Auto-numbered enum. Convert `int_tag_val` to field index.
446 switch (ip.indexToKey(int_tag_val).int.storage) {
447 .u64 => |x| {
448 if (x >= self.names.len) return null;
449 return @intCast(u32, x);
450 },
451 .i64, .big_int => return null, // out of range
452 .lazy_align, .lazy_size => unreachable,
453 }
454 }
455 };
456
457 pub const IncompleteEnumType = struct {
458 /// Same as corresponding `EnumType` field.
459 decl: Module.Decl.Index,
460 /// Same as corresponding `EnumType` field.
461 namespace: Module.Namespace.OptionalIndex,
462 /// The field names and field values are not known yet, but
463 /// the number of fields must be known ahead of time.
464 fields_len: u32,
465 /// This information is needed so that the size does not change
466 /// later when populating field values.
467 has_values: bool,
468 /// Same as corresponding `EnumType` field.
469 tag_mode: EnumType.TagMode,
470 /// This may be updated via `setTagType` later.
471 tag_ty: Index = .none,
472
473 pub fn toEnumType(self: @This()) EnumType {
474 return .{
475 .decl = self.decl,
476 .namespace = self.namespace,
477 .tag_ty = self.tag_ty,
478 .tag_mode = self.tag_mode,
479 .names = &.{},
480 .values = &.{},
481 };
482 }
483
484 /// Only the decl is used for hashing and equality, so we can construct
485 /// this minimal key for use with `map`.
486 pub fn toKey(self: @This()) Key {
487 return .{ .enum_type = self.toEnumType() };
488 }
489 };
490
491 pub const FuncType = struct {
492 param_types: []Index,
493 return_type: Index,
494 /// Tells whether a parameter is comptime. See `paramIsComptime` helper
495 /// method for accessing this.
496 comptime_bits: u32,
497 /// Tells whether a parameter is noalias. See `paramIsNoalias` helper
498 /// method for accessing this.
499 noalias_bits: u32,
500 /// `none` indicates the function has the default alignment for
501 /// function code on the target. In this case, this field *must* be set
502 /// to `none`, otherwise the `InternPool` equality and hashing
503 /// functions will return incorrect results.
504 alignment: Alignment,
505 cc: std.builtin.CallingConvention,
506 is_var_args: bool,
507 is_generic: bool,
508 is_noinline: bool,
509 align_is_generic: bool,
510 cc_is_generic: bool,
511 section_is_generic: bool,
512 addrspace_is_generic: bool,
513
514 pub fn paramIsComptime(self: @This(), i: u5) bool {
515 assert(i < self.param_types.len);
516 return @truncate(u1, self.comptime_bits >> i) != 0;
517 }
518
519 pub fn paramIsNoalias(self: @This(), i: u5) bool {
520 assert(i < self.param_types.len);
521 return @truncate(u1, self.noalias_bits >> i) != 0;
522 }
523 };
524
525 pub const Variable = struct {
526 ty: Index,
527 init: Index,
528 decl: Module.Decl.Index,
529 lib_name: OptionalNullTerminatedString = .none,
530 is_extern: bool = false,
531 is_const: bool = false,
532 is_threadlocal: bool = false,
533 is_weak_linkage: bool = false,
534 };
535
536 pub const ExternFunc = struct {
537 ty: Index,
538 /// The Decl that corresponds to the function itself.
539 decl: Module.Decl.Index,
540 /// Library name if specified.
541 /// For example `extern "c" fn write(...) usize` would have 'c' as library name.
542 /// Index into the string table bytes.
543 lib_name: OptionalNullTerminatedString,
544 };
545
546 /// Extern so it can be hashed by reinterpreting memory.
547 pub const Func = extern struct {
548 ty: Index,
549 index: Module.Fn.Index,
550 };
551
552 pub const Int = struct {
553 ty: Index,
554 storage: Storage,
555
556 pub const Storage = union(enum) {
557 u64: u64,
558 i64: i64,
559 big_int: BigIntConst,
560 lazy_align: Index,
561 lazy_size: Index,
562
563 /// Big enough to fit any non-BigInt value
564 pub const BigIntSpace = struct {
565 /// The +1 is headroom so that operations such as incrementing once
566 /// or decrementing once are possible without using an allocator.
567 limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
568 };
569
570 pub fn toBigInt(storage: Storage, space: *BigIntSpace) BigIntConst {
571 return switch (storage) {
572 .big_int => |x| x,
573 inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(),
574 .lazy_align, .lazy_size => unreachable,
575 };
576 }
577 };
578 };
579
580 pub const Error = extern struct {
581 ty: Index,
582 name: NullTerminatedString,
583 };
584
585 pub const ErrorUnion = struct {
586 ty: Index,
587 val: Value,
588
589 pub const Value = union(enum) {
590 err_name: NullTerminatedString,
591 payload: Index,
592 };
593 };
594
595 pub const EnumTag = extern struct {
596 /// The enum type.
597 ty: Index,
598 /// The integer tag value which has the integer tag type of the enum.
599 int: Index,
600 };
601
602 pub const Float = struct {
603 ty: Index,
604 /// The storage used must match the size of the float type being represented.
605 storage: Storage,
606
607 pub const Storage = union(enum) {
608 f16: f16,
609 f32: f32,
610 f64: f64,
611 f80: f80,
612 f128: f128,
613 };
614 };
615
616 pub const Ptr = struct {
617 /// This is the pointer type, not the element type.
618 ty: Index,
619 /// The value of the address that the pointer points to.
620 addr: Addr,
621 /// This could be `none` if size is not a slice.
622 len: Index = .none,
623
624 pub const Addr = union(enum) {
625 decl: Module.Decl.Index,
626 mut_decl: MutDecl,
627 comptime_field: Index,
628 int: Index,
629 eu_payload: Index,
630 opt_payload: Index,
631 elem: BaseIndex,
632 field: BaseIndex,
633
634 pub const MutDecl = struct {
635 decl: Module.Decl.Index,
636 runtime_index: RuntimeIndex,
637 };
638 pub const BaseIndex = struct {
639 base: Index,
640 index: u64,
641 };
642 };
643 };
644
645 /// `null` is represented by the `val` field being `none`.
646 pub const Opt = extern struct {
647 /// This is the optional type; not the payload type.
648 ty: Index,
649 /// This could be `none`, indicating the optional is `null`.
650 val: Index,
651 };
652
653 pub const Union = extern struct {
654 /// This is the union type; not the field type.
655 ty: Index,
656 /// Indicates the active field.
657 tag: Index,
658 /// The value of the active field.
659 val: Index,
660 };
661
662 pub const Aggregate = struct {
663 ty: Index,
664 storage: Storage,
665
666 pub const Storage = union(enum) {
667 bytes: []const u8,
668 elems: []const Index,
669 repeated_elem: Index,
670
671 pub fn values(self: *const Storage) []const Index {
672 return switch (self.*) {
673 .bytes => &.{},
674 .elems => |elems| elems,
675 .repeated_elem => |*elem| @as(*const [1]Index, elem),
676 };
677 }
678 };
679 };
680
681 pub const MemoizedCall = struct {
682 func: Module.Fn.Index,
683 arg_values: []const Index,
684 result: Index,
685 };
686
687 pub fn hash32(key: Key, ip: *const InternPool) u32 {
688 return @truncate(u32, key.hash64(ip));
689 }
690
691 pub fn hash64(key: Key, ip: *const InternPool) u64 {
692 const asBytes = std.mem.asBytes;
693 const KeyTag = @typeInfo(Key).Union.tag_type.?;
694 const seed = @enumToInt(@as(KeyTag, key));
695 return switch (key) {
696 // TODO: assert no padding in these types
697 inline .ptr_type,
698 .func,
699 .array_type,
700 .vector_type,
701 .opt_type,
702 .anyframe_type,
703 .error_union_type,
704 .simple_type,
705 .simple_value,
706 .opt,
707 .struct_type,
708 .undef,
709 .err,
710 .enum_literal,
711 .enum_tag,
712 .empty_enum_value,
713 .inferred_error_set_type,
714 .un,
715 => |x| Hash.hash(seed, asBytes(&x)),
716
717 .int_type => |x| Hash.hash(seed + @enumToInt(x.signedness), asBytes(&x.bits)),
718 .union_type => |x| Hash.hash(seed + @enumToInt(x.runtime_tag), asBytes(&x.index)),
719
720 .error_union => |x| switch (x.val) {
721 .err_name => |y| Hash.hash(seed + 0, asBytes(&x.ty) ++ asBytes(&y)),
722 .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)),
723 },
724
725 .runtime_value => |x| Hash.hash(seed, asBytes(&x.val)),
726 .opaque_type => |x| Hash.hash(seed, asBytes(&x.decl)),
727
728 .enum_type => |enum_type| {
729 var hasher = Hash.init(seed);
730 std.hash.autoHash(&hasher, enum_type.decl);
731 return hasher.final();
732 },
733
734 .variable => |variable| {
735 var hasher = Hash.init(seed);
736 std.hash.autoHash(&hasher, variable.decl);
737 return hasher.final();
738 },
739 .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)),
740
741 .int => |int| {
742 var hasher = Hash.init(seed);
743 // Canonicalize all integers by converting them to BigIntConst.
744 switch (int.storage) {
745 .u64, .i64, .big_int => {
746 var buffer: Key.Int.Storage.BigIntSpace = undefined;
747 const big_int = int.storage.toBigInt(&buffer);
748
749 std.hash.autoHash(&hasher, int.ty);
750 std.hash.autoHash(&hasher, big_int.positive);
751 for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb);
752 },
753 .lazy_align, .lazy_size => |lazy_ty| {
754 std.hash.autoHash(
755 &hasher,
756 @as(@typeInfo(Key.Int.Storage).Union.tag_type.?, int.storage),
757 );
758 std.hash.autoHash(&hasher, lazy_ty);
759 },
760 }
761 return hasher.final();
762 },
763
764 .float => |float| {
765 var hasher = Hash.init(seed);
766 std.hash.autoHash(&hasher, float.ty);
767 switch (float.storage) {
768 inline else => |val| std.hash.autoHash(
769 &hasher,
770 @bitCast(std.meta.Int(.unsigned, @bitSizeOf(@TypeOf(val))), val),
771 ),
772 }
773 return hasher.final();
774 },
775
776 .ptr => |ptr| {
777 // Int-to-ptr pointers are hashed separately than decl-referencing pointers.
778 // This is sound due to pointer provenance rules.
779 const addr: @typeInfo(Key.Ptr.Addr).Union.tag_type.? = ptr.addr;
780 const seed2 = seed + @enumToInt(addr);
781 const common = asBytes(&ptr.ty) ++ asBytes(&ptr.len);
782 return switch (ptr.addr) {
783 .decl => |x| Hash.hash(seed2, common ++ asBytes(&x)),
784
785 .mut_decl => |x| Hash.hash(
786 seed2,
787 asBytes(&x.decl) ++ asBytes(&x.runtime_index),
788 ),
789
790 .int, .eu_payload, .opt_payload, .comptime_field => |int| Hash.hash(
791 seed2,
792 asBytes(&int),
793 ),
794
795 .elem, .field => |x| Hash.hash(
796 seed2,
797 asBytes(&x.base) ++ asBytes(&x.index),
798 ),
799 };
800 },
801
802 .aggregate => |aggregate| {
803 var hasher = Hash.init(seed);
804 std.hash.autoHash(&hasher, aggregate.ty);
805 const len = ip.aggregateTypeLen(aggregate.ty);
806 const child = switch (ip.indexToKey(aggregate.ty)) {
807 .array_type => |array_type| array_type.child,
808 .vector_type => |vector_type| vector_type.child,
809 .anon_struct_type, .struct_type => .none,
810 else => unreachable,
811 };
812
813 if (child == .u8_type) {
814 switch (aggregate.storage) {
815 .bytes => |bytes| for (bytes[0..@intCast(usize, len)]) |byte| {
816 std.hash.autoHash(&hasher, KeyTag.int);
817 std.hash.autoHash(&hasher, byte);
818 },
819 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem| {
820 const elem_key = ip.indexToKey(elem);
821 std.hash.autoHash(&hasher, @as(KeyTag, elem_key));
822 switch (elem_key) {
823 .undef => {},
824 .int => |int| std.hash.autoHash(
825 &hasher,
826 @intCast(u8, int.storage.u64),
827 ),
828 else => unreachable,
829 }
830 },
831 .repeated_elem => |elem| {
832 const elem_key = ip.indexToKey(elem);
833 var remaining = len;
834 while (remaining > 0) : (remaining -= 1) {
835 std.hash.autoHash(&hasher, @as(KeyTag, elem_key));
836 switch (elem_key) {
837 .undef => {},
838 .int => |int| std.hash.autoHash(
839 &hasher,
840 @intCast(u8, int.storage.u64),
841 ),
842 else => unreachable,
843 }
844 }
845 },
846 }
847 return hasher.final();
848 }
849
850 switch (aggregate.storage) {
851 .bytes => unreachable,
852 .elems => |elems| for (elems[0..@intCast(usize, len)]) |elem|
853 std.hash.autoHash(&hasher, elem),
854 .repeated_elem => |elem| {
855 var remaining = len;
856 while (remaining > 0) : (remaining -= 1) std.hash.autoHash(&hasher, elem);
857 },
858 }
859 return hasher.final();
860 },
861
862 .error_set_type => |error_set_type| {
863 var hasher = Hash.init(seed);
864 for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem);
865 return hasher.final();
866 },
867
868 .anon_struct_type => |anon_struct_type| {
869 var hasher = Hash.init(seed);
870 for (anon_struct_type.types) |elem| std.hash.autoHash(&hasher, elem);
871 for (anon_struct_type.values) |elem| std.hash.autoHash(&hasher, elem);
872 for (anon_struct_type.names) |elem| std.hash.autoHash(&hasher, elem);
873 return hasher.final();
874 },
875
876 .func_type => |func_type| {
877 var hasher = Hash.init(seed);
878 for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type);
879 std.hash.autoHash(&hasher, func_type.return_type);
880 std.hash.autoHash(&hasher, func_type.comptime_bits);
881 std.hash.autoHash(&hasher, func_type.noalias_bits);
882 std.hash.autoHash(&hasher, func_type.alignment);
883 std.hash.autoHash(&hasher, func_type.cc);
884 std.hash.autoHash(&hasher, func_type.is_var_args);
885 std.hash.autoHash(&hasher, func_type.is_generic);
886 std.hash.autoHash(&hasher, func_type.is_noinline);
887 return hasher.final();
888 },
889
890 .memoized_call => |memoized_call| {
891 var hasher = Hash.init(seed);
892 std.hash.autoHash(&hasher, memoized_call.func);
893 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg);
894 return hasher.final();
895 },
896 };
897 }
898
899 pub fn eql(a: Key, b: Key, ip: *const InternPool) bool {
900 const KeyTag = @typeInfo(Key).Union.tag_type.?;
901 const a_tag: KeyTag = a;
902 const b_tag: KeyTag = b;
903 if (a_tag != b_tag) return false;
904 switch (a) {
905 .int_type => |a_info| {
906 const b_info = b.int_type;
907 return std.meta.eql(a_info, b_info);
908 },
909 .ptr_type => |a_info| {
910 const b_info = b.ptr_type;
911 return std.meta.eql(a_info, b_info);
912 },
913 .array_type => |a_info| {
914 const b_info = b.array_type;
915 return std.meta.eql(a_info, b_info);
916 },
917 .vector_type => |a_info| {
918 const b_info = b.vector_type;
919 return std.meta.eql(a_info, b_info);
920 },
921 .opt_type => |a_info| {
922 const b_info = b.opt_type;
923 return a_info == b_info;
924 },
925 .anyframe_type => |a_info| {
926 const b_info = b.anyframe_type;
927 return a_info == b_info;
928 },
929 .error_union_type => |a_info| {
930 const b_info = b.error_union_type;
931 return std.meta.eql(a_info, b_info);
932 },
933 .simple_type => |a_info| {
934 const b_info = b.simple_type;
935 return a_info == b_info;
936 },
937 .simple_value => |a_info| {
938 const b_info = b.simple_value;
939 return a_info == b_info;
940 },
941 .undef => |a_info| {
942 const b_info = b.undef;
943 return a_info == b_info;
944 },
945 .runtime_value => |a_info| {
946 const b_info = b.runtime_value;
947 return a_info.val == b_info.val;
948 },
949 .opt => |a_info| {
950 const b_info = b.opt;
951 return std.meta.eql(a_info, b_info);
952 },
953 .struct_type => |a_info| {
954 const b_info = b.struct_type;
955 return std.meta.eql(a_info, b_info);
956 },
957 .union_type => |a_info| {
958 const b_info = b.union_type;
959 return std.meta.eql(a_info, b_info);
960 },
961 .un => |a_info| {
962 const b_info = b.un;
963 return std.meta.eql(a_info, b_info);
964 },
965 .err => |a_info| {
966 const b_info = b.err;
967 return std.meta.eql(a_info, b_info);
968 },
969 .error_union => |a_info| {
970 const b_info = b.error_union;
971 return std.meta.eql(a_info, b_info);
972 },
973 .enum_literal => |a_info| {
974 const b_info = b.enum_literal;
975 return a_info == b_info;
976 },
977 .enum_tag => |a_info| {
978 const b_info = b.enum_tag;
979 return std.meta.eql(a_info, b_info);
980 },
981 .empty_enum_value => |a_info| {
982 const b_info = b.empty_enum_value;
983 return a_info == b_info;
984 },
985
986 .variable => |a_info| {
987 const b_info = b.variable;
988 return a_info.decl == b_info.decl;
989 },
990 .extern_func => |a_info| {
991 const b_info = b.extern_func;
992 return a_info.ty == b_info.ty and a_info.decl == b_info.decl;
993 },
994 .func => |a_info| {
995 const b_info = b.func;
996 return a_info.ty == b_info.ty and a_info.index == b_info.index;
997 },
998
999 .ptr => |a_info| {
1000 const b_info = b.ptr;
1001 if (a_info.ty != b_info.ty or a_info.len != b_info.len) return false;
1002
1003 const AddrTag = @typeInfo(Key.Ptr.Addr).Union.tag_type.?;
1004 if (@as(AddrTag, a_info.addr) != @as(AddrTag, b_info.addr)) return false;
1005
1006 return switch (a_info.addr) {
1007 .decl => |a_decl| a_decl == b_info.addr.decl,
1008 .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),
1009 .int => |a_int| a_int == b_info.addr.int,
1010 .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload,
1011 .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload,
1012 .comptime_field => |a_comptime_field| a_comptime_field == b_info.addr.comptime_field,
1013 .elem => |a_elem| std.meta.eql(a_elem, b_info.addr.elem),
1014 .field => |a_field| std.meta.eql(a_field, b_info.addr.field),
1015 };
1016 },
1017
1018 .int => |a_info| {
1019 const b_info = b.int;
1020
1021 if (a_info.ty != b_info.ty)
1022 return false;
1023
1024 return switch (a_info.storage) {
1025 .u64 => |aa| switch (b_info.storage) {
1026 .u64 => |bb| aa == bb,
1027 .i64 => |bb| aa == bb,
1028 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
1029 .lazy_align, .lazy_size => false,
1030 },
1031 .i64 => |aa| switch (b_info.storage) {
1032 .u64 => |bb| aa == bb,
1033 .i64 => |bb| aa == bb,
1034 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq,
1035 .lazy_align, .lazy_size => false,
1036 },
1037 .big_int => |aa| switch (b_info.storage) {
1038 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq,
1039 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq,
1040 .big_int => |bb| aa.eq(bb),
1041 .lazy_align, .lazy_size => false,
1042 },
1043 .lazy_align => |aa| switch (b_info.storage) {
1044 .u64, .i64, .big_int, .lazy_size => false,
1045 .lazy_align => |bb| aa == bb,
1046 },
1047 .lazy_size => |aa| switch (b_info.storage) {
1048 .u64, .i64, .big_int, .lazy_align => false,
1049 .lazy_size => |bb| aa == bb,
1050 },
1051 };
1052 },
1053
1054 .float => |a_info| {
1055 const b_info = b.float;
1056
1057 if (a_info.ty != b_info.ty)
1058 return false;
1059
1060 if (a_info.ty == .c_longdouble_type and a_info.storage != .f80) {
1061 // These are strange: we'll sometimes represent them as f128, even if the
1062 // underlying type is smaller. f80 is an exception: see float_c_longdouble_f80.
1063 const a_val = switch (a_info.storage) {
1064 inline else => |val| @floatCast(f128, val),
1065 };
1066 const b_val = switch (b_info.storage) {
1067 inline else => |val| @floatCast(f128, val),
1068 };
1069 return a_val == b_val;
1070 }
1071
1072 const StorageTag = @typeInfo(Key.Float.Storage).Union.tag_type.?;
1073 assert(@as(StorageTag, a_info.storage) == @as(StorageTag, b_info.storage));
1074
1075 return switch (a_info.storage) {
1076 inline else => |val, tag| val == @field(b_info.storage, @tagName(tag)),
1077 };
1078 },
1079
1080 .opaque_type => |a_info| {
1081 const b_info = b.opaque_type;
1082 return a_info.decl == b_info.decl;
1083 },
1084 .enum_type => |a_info| {
1085 const b_info = b.enum_type;
1086 return a_info.decl == b_info.decl;
1087 },
1088 .aggregate => |a_info| {
1089 const b_info = b.aggregate;
1090 if (a_info.ty != b_info.ty) return false;
1091
1092 const len = ip.aggregateTypeLen(a_info.ty);
1093 const StorageTag = @typeInfo(Key.Aggregate.Storage).Union.tag_type.?;
1094 if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) {
1095 for (0..@intCast(usize, len)) |elem_index| {
1096 const a_elem = switch (a_info.storage) {
1097 .bytes => |bytes| ip.getIfExists(.{ .int = .{
1098 .ty = .u8_type,
1099 .storage = .{ .u64 = bytes[elem_index] },
1100 } }) orelse return false,
1101 .elems => |elems| elems[elem_index],
1102 .repeated_elem => |elem| elem,
1103 };
1104 const b_elem = switch (b_info.storage) {
1105 .bytes => |bytes| ip.getIfExists(.{ .int = .{
1106 .ty = .u8_type,
1107 .storage = .{ .u64 = bytes[elem_index] },
1108 } }) orelse return false,
1109 .elems => |elems| elems[elem_index],
1110 .repeated_elem => |elem| elem,
1111 };
1112 if (a_elem != b_elem) return false;
1113 }
1114 return true;
1115 }
1116
1117 switch (a_info.storage) {
1118 .bytes => |a_bytes| {
1119 const b_bytes = b_info.storage.bytes;
1120 return std.mem.eql(
1121 u8,
1122 a_bytes[0..@intCast(usize, len)],
1123 b_bytes[0..@intCast(usize, len)],
1124 );
1125 },
1126 .elems => |a_elems| {
1127 const b_elems = b_info.storage.elems;
1128 return std.mem.eql(
1129 Index,
1130 a_elems[0..@intCast(usize, len)],
1131 b_elems[0..@intCast(usize, len)],
1132 );
1133 },
1134 .repeated_elem => |a_elem| {
1135 const b_elem = b_info.storage.repeated_elem;
1136 return a_elem == b_elem;
1137 },
1138 }
1139 },
1140 .anon_struct_type => |a_info| {
1141 const b_info = b.anon_struct_type;
1142 return std.mem.eql(Index, a_info.types, b_info.types) and
1143 std.mem.eql(Index, a_info.values, b_info.values) and
1144 std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
1145 },
1146 .error_set_type => |a_info| {
1147 const b_info = b.error_set_type;
1148 return std.mem.eql(NullTerminatedString, a_info.names, b_info.names);
1149 },
1150 .inferred_error_set_type => |a_info| {
1151 const b_info = b.inferred_error_set_type;
1152 return a_info == b_info;
1153 },
1154
1155 .func_type => |a_info| {
1156 const b_info = b.func_type;
1157
1158 return std.mem.eql(Index, a_info.param_types, b_info.param_types) and
1159 a_info.return_type == b_info.return_type and
1160 a_info.comptime_bits == b_info.comptime_bits and
1161 a_info.noalias_bits == b_info.noalias_bits and
1162 a_info.alignment == b_info.alignment and
1163 a_info.cc == b_info.cc and
1164 a_info.is_var_args == b_info.is_var_args and
1165 a_info.is_generic == b_info.is_generic and
1166 a_info.is_noinline == b_info.is_noinline;
1167 },
1168
1169 .memoized_call => |a_info| {
1170 const b_info = b.memoized_call;
1171 return a_info.func == b_info.func and
1172 std.mem.eql(Index, a_info.arg_values, b_info.arg_values);
1173 },
1174 }
1175 }
1176
1177 pub fn typeOf(key: Key) Index {
1178 return switch (key) {
1179 .int_type,
1180 .ptr_type,
1181 .array_type,
1182 .vector_type,
1183 .opt_type,
1184 .anyframe_type,
1185 .error_union_type,
1186 .error_set_type,
1187 .inferred_error_set_type,
1188 .simple_type,
1189 .struct_type,
1190 .union_type,
1191 .opaque_type,
1192 .enum_type,
1193 .anon_struct_type,
1194 .func_type,
1195 => .type_type,
1196
1197 inline .runtime_value,
1198 .ptr,
1199 .int,
1200 .float,
1201 .opt,
1202 .variable,
1203 .extern_func,
1204 .func,
1205 .err,
1206 .error_union,
1207 .enum_tag,
1208 .aggregate,
1209 .un,
1210 => |x| x.ty,
1211
1212 .enum_literal => .enum_literal_type,
1213
1214 .undef => |x| x,
1215 .empty_enum_value => |x| x,
1216
1217 .simple_value => |s| switch (s) {
1218 .undefined => .undefined_type,
1219 .void => .void_type,
1220 .null => .null_type,
1221 .false, .true => .bool_type,
1222 .empty_struct => .empty_struct_type,
1223 .@"unreachable" => .noreturn_type,
1224 .generic_poison => .generic_poison_type,
1225 },
1226
1227 .memoized_call => unreachable,
1228 };
1229 }
1230};
1231
1232pub const Item = struct {
1233 tag: Tag,
1234 /// The doc comments on the respective Tag explain how to interpret this.
1235 data: u32,
1236};
1237
1238/// Represents an index into `map`. It represents the canonical index
1239/// of a `Value` within this `InternPool`. The values are typed.
1240/// Two values which have the same type can be equality compared simply
1241/// by checking if their indexes are equal, provided they are both in
1242/// the same `InternPool`.
1243/// When adding a tag to this enum, consider adding a corresponding entry to
1244/// `primitives` in AstGen.zig.
1245pub const Index = enum(u32) {
1246 pub const first_type: Index = .u1_type;
1247 pub const last_type: Index = .empty_struct_type;
1248 pub const first_value: Index = .undef;
1249 pub const last_value: Index = .empty_struct;
1250
1251 u1_type,
1252 u8_type,
1253 i8_type,
1254 u16_type,
1255 i16_type,
1256 u29_type,
1257 u32_type,
1258 i32_type,
1259 u64_type,
1260 i64_type,
1261 u80_type,
1262 u128_type,
1263 i128_type,
1264 usize_type,
1265 isize_type,
1266 c_char_type,
1267 c_short_type,
1268 c_ushort_type,
1269 c_int_type,
1270 c_uint_type,
1271 c_long_type,
1272 c_ulong_type,
1273 c_longlong_type,
1274 c_ulonglong_type,
1275 c_longdouble_type,
1276 f16_type,
1277 f32_type,
1278 f64_type,
1279 f80_type,
1280 f128_type,
1281 anyopaque_type,
1282 bool_type,
1283 void_type,
1284 type_type,
1285 anyerror_type,
1286 comptime_int_type,
1287 comptime_float_type,
1288 noreturn_type,
1289 anyframe_type,
1290 null_type,
1291 undefined_type,
1292 enum_literal_type,
1293 atomic_order_type,
1294 atomic_rmw_op_type,
1295 calling_convention_type,
1296 address_space_type,
1297 float_mode_type,
1298 reduce_op_type,
1299 call_modifier_type,
1300 prefetch_options_type,
1301 export_options_type,
1302 extern_options_type,
1303 type_info_type,
1304 manyptr_u8_type,
1305 manyptr_const_u8_type,
1306 manyptr_const_u8_sentinel_0_type,
1307 single_const_pointer_to_comptime_int_type,
1308 slice_const_u8_type,
1309 slice_const_u8_sentinel_0_type,
1310 anyerror_void_error_union_type,
1311 generic_poison_type,
1312 /// `@TypeOf(.{})`
1313 empty_struct_type,
1314
1315 /// `undefined` (untyped)
1316 undef,
1317 /// `0` (comptime_int)
1318 zero,
1319 /// `0` (usize)
1320 zero_usize,
1321 /// `0` (u8)
1322 zero_u8,
1323 /// `1` (comptime_int)
1324 one,
1325 /// `1` (usize)
1326 one_usize,
1327 /// `1` (u8)
1328 one_u8,
1329 /// `4` (u8)
1330 four_u8,
1331 /// `-1` (comptime_int)
1332 negative_one,
1333 /// `std.builtin.CallingConvention.C`
1334 calling_convention_c,
1335 /// `std.builtin.CallingConvention.Inline`
1336 calling_convention_inline,
1337 /// `{}`
1338 void_value,
1339 /// `unreachable` (noreturn type)
1340 unreachable_value,
1341 /// `null` (untyped)
1342 null_value,
1343 /// `true`
1344 bool_true,
1345 /// `false`
1346 bool_false,
1347 /// `.{}` (untyped)
1348 empty_struct,
1349
1350 /// Used for generic parameters where the type and value
1351 /// is not known until generic function instantiation.
1352 generic_poison,
1353
1354 /// Used by Air/Sema only.
1355 var_args_param_type = std.math.maxInt(u32) - 1,
1356 none = std.math.maxInt(u32),
1357
1358 _,
1359
1360 pub fn toType(i: Index) @import("type.zig").Type {
1361 assert(i != .none);
1362 return .{ .ip_index = i };
1363 }
1364
1365 pub fn toValue(i: Index) @import("value.zig").Value {
1366 assert(i != .none);
1367 return .{
1368 .ip_index = i,
1369 .legacy = undefined,
1370 };
1371 }
1372
1373 /// Used for a map of `Index` values to the index within a list of `Index` values.
1374 const Adapter = struct {
1375 indexes: []const Index,
1376
1377 pub fn eql(ctx: @This(), a: Index, b_void: void, b_map_index: usize) bool {
1378 _ = b_void;
1379 return a == ctx.indexes[b_map_index];
1380 }
1381
1382 pub fn hash(ctx: @This(), a: Index) u32 {
1383 _ = ctx;
1384 return std.hash.uint32(@enumToInt(a));
1385 }
1386 };
1387
1388 /// This function is used in the debugger pretty formatters in tools/ to fetch the
1389 /// Tag to encoding mapping to facilitate fancy debug printing for this type.
1390 fn dbHelper(self: *Index, tag_to_encoding_map: *struct {
1391 const DataIsIndex = struct { data: Index };
1392 const DataIsExtraIndexOfEnumExplicit = struct {
1393 const @"data.fields_len" = opaque {};
1394 data: *EnumExplicit,
1395 @"trailing.names.len": *@"data.fields_len",
1396 @"trailing.values.len": *@"data.fields_len",
1397 trailing: struct {
1398 names: []NullTerminatedString,
1399 values: []Index,
1400 },
1401 };
1402 const DataIsExtraIndexOfTypeStructAnon = struct {
1403 const @"data.fields_len" = opaque {};
1404 data: *TypeStructAnon,
1405 @"trailing.types.len": *@"data.fields_len",
1406 @"trailing.values.len": *@"data.fields_len",
1407 @"trailing.names.len": *@"data.fields_len",
1408 trailing: struct {
1409 types: []Index,
1410 values: []Index,
1411 names: []NullTerminatedString,
1412 },
1413 };
1414
1415 type_int_signed: struct { data: u32 },
1416 type_int_unsigned: struct { data: u32 },
1417 type_array_big: struct { data: *Array },
1418 type_array_small: struct { data: *Vector },
1419 type_vector: struct { data: *Vector },
1420 type_pointer: struct { data: *Tag.TypePointer },
1421 type_slice: DataIsIndex,
1422 type_optional: DataIsIndex,
1423 type_anyframe: DataIsIndex,
1424 type_error_union: struct { data: *Key.ErrorUnionType },
1425 type_error_set: struct {
1426 const @"data.names_len" = opaque {};
1427 data: *ErrorSet,
1428 @"trailing.names.len": *@"data.names_len",
1429 trailing: struct { names: []NullTerminatedString },
1430 },
1431 type_inferred_error_set: struct { data: Module.Fn.InferredErrorSet.Index },
1432 type_enum_auto: struct {
1433 const @"data.fields_len" = opaque {};
1434 data: *EnumAuto,
1435 @"trailing.names.len": *@"data.fields_len",
1436 trailing: struct { names: []NullTerminatedString },
1437 },
1438 type_enum_explicit: DataIsExtraIndexOfEnumExplicit,
1439 type_enum_nonexhaustive: DataIsExtraIndexOfEnumExplicit,
1440 simple_type: struct { data: SimpleType },
1441 type_opaque: struct { data: *Key.OpaqueType },
1442 type_struct: struct { data: Module.Struct.OptionalIndex },
1443 type_struct_ns: struct { data: Module.Namespace.Index },
1444 type_struct_anon: DataIsExtraIndexOfTypeStructAnon,
1445 type_tuple_anon: DataIsExtraIndexOfTypeStructAnon,
1446 type_union_tagged: struct { data: Module.Union.Index },
1447 type_union_untagged: struct { data: Module.Union.Index },
1448 type_union_safety: struct { data: Module.Union.Index },
1449 type_function: struct {
1450 const @"data.params_len" = opaque {};
1451 data: *TypeFunction,
1452 @"trailing.param_types.len": *@"data.params_len",
1453 trailing: struct { param_types: []Index },
1454 },
1455
1456 undef: DataIsIndex,
1457 runtime_value: struct { data: *Tag.TypeValue },
1458 simple_value: struct { data: SimpleValue },
1459 ptr_decl: struct { data: *PtrDecl },
1460 ptr_mut_decl: struct { data: *PtrMutDecl },
1461 ptr_comptime_field: struct { data: *PtrComptimeField },
1462 ptr_int: struct { data: *PtrBase },
1463 ptr_eu_payload: struct { data: *PtrBase },
1464 ptr_opt_payload: struct { data: *PtrBase },
1465 ptr_elem: struct { data: *PtrBaseIndex },
1466 ptr_field: struct { data: *PtrBaseIndex },
1467 ptr_slice: struct { data: *PtrSlice },
1468 opt_payload: struct { data: *Tag.TypeValue },
1469 opt_null: DataIsIndex,
1470 int_u8: struct { data: u8 },
1471 int_u16: struct { data: u16 },
1472 int_u32: struct { data: u32 },
1473 int_i32: struct { data: i32 },
1474 int_usize: struct { data: u32 },
1475 int_comptime_int_u32: struct { data: u32 },
1476 int_comptime_int_i32: struct { data: i32 },
1477 int_small: struct { data: *IntSmall },
1478 int_positive: struct { data: u32 },
1479 int_negative: struct { data: u32 },
1480 int_lazy_align: struct { data: *IntLazy },
1481 int_lazy_size: struct { data: *IntLazy },
1482 error_set_error: struct { data: *Key.Error },
1483 error_union_error: struct { data: *Key.Error },
1484 error_union_payload: struct { data: *Tag.TypeValue },
1485 enum_literal: struct { data: NullTerminatedString },
1486 enum_tag: struct { data: *Tag.EnumTag },
1487 float_f16: struct { data: f16 },
1488 float_f32: struct { data: f32 },
1489 float_f64: struct { data: *Float64 },
1490 float_f80: struct { data: *Float80 },
1491 float_f128: struct { data: *Float128 },
1492 float_c_longdouble_f80: struct { data: *Float80 },
1493 float_c_longdouble_f128: struct { data: *Float128 },
1494 float_comptime_float: struct { data: *Float128 },
1495 variable: struct { data: *Tag.Variable },
1496 extern_func: struct { data: *Key.ExternFunc },
1497 func: struct { data: *Tag.Func },
1498 only_possible_value: DataIsIndex,
1499 union_value: struct { data: *Key.Union },
1500 bytes: struct { data: *Bytes },
1501 aggregate: struct {
1502 const @"data.ty.data.len orelse data.ty.data.fields_len" = opaque {};
1503 data: *Tag.Aggregate,
1504 @"trailing.element_values.len": *@"data.ty.data.len orelse data.ty.data.fields_len",
1505 trailing: struct { element_values: []Index },
1506 },
1507 repeated: struct { data: *Repeated },
1508
1509 memoized_call: struct {
1510 const @"data.args_len" = opaque {};
1511 data: *MemoizedCall,
1512 @"trailing.arg_values.len": *@"data.args_len",
1513 trailing: struct { arg_values: []Index },
1514 },
1515 }) void {
1516 _ = self;
1517 const map_fields = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).Pointer.child).Struct.fields;
1518 @setEvalBranchQuota(2_000);
1519 inline for (@typeInfo(Tag).Enum.fields, 0..) |tag, start| {
1520 inline for (0..map_fields.len) |offset| {
1521 if (comptime std.mem.eql(u8, tag.name, map_fields[(start + offset) % map_fields.len].name)) break;
1522 } else {
1523 @compileError(@typeName(Tag) ++ "." ++ tag.name ++ " missing dbHelper tag_to_encoding_map entry");
1524 }
1525 }
1526 }
1527
1528 comptime {
1529 if (builtin.mode == .Debug) {
1530 _ = &dbHelper;
1531 }
1532 }
1533};
1534
1535pub const static_keys = [_]Key{
1536 .{ .int_type = .{
1537 .signedness = .unsigned,
1538 .bits = 1,
1539 } },
1540
1541 .{ .int_type = .{
1542 .signedness = .unsigned,
1543 .bits = 8,
1544 } },
1545
1546 .{ .int_type = .{
1547 .signedness = .signed,
1548 .bits = 8,
1549 } },
1550
1551 .{ .int_type = .{
1552 .signedness = .unsigned,
1553 .bits = 16,
1554 } },
1555
1556 .{ .int_type = .{
1557 .signedness = .signed,
1558 .bits = 16,
1559 } },
1560
1561 .{ .int_type = .{
1562 .signedness = .unsigned,
1563 .bits = 29,
1564 } },
1565
1566 .{ .int_type = .{
1567 .signedness = .unsigned,
1568 .bits = 32,
1569 } },
1570
1571 .{ .int_type = .{
1572 .signedness = .signed,
1573 .bits = 32,
1574 } },
1575
1576 .{ .int_type = .{
1577 .signedness = .unsigned,
1578 .bits = 64,
1579 } },
1580
1581 .{ .int_type = .{
1582 .signedness = .signed,
1583 .bits = 64,
1584 } },
1585
1586 .{ .int_type = .{
1587 .signedness = .unsigned,
1588 .bits = 80,
1589 } },
1590
1591 .{ .int_type = .{
1592 .signedness = .unsigned,
1593 .bits = 128,
1594 } },
1595
1596 .{ .int_type = .{
1597 .signedness = .signed,
1598 .bits = 128,
1599 } },
1600
1601 .{ .simple_type = .usize },
1602 .{ .simple_type = .isize },
1603 .{ .simple_type = .c_char },
1604 .{ .simple_type = .c_short },
1605 .{ .simple_type = .c_ushort },
1606 .{ .simple_type = .c_int },
1607 .{ .simple_type = .c_uint },
1608 .{ .simple_type = .c_long },
1609 .{ .simple_type = .c_ulong },
1610 .{ .simple_type = .c_longlong },
1611 .{ .simple_type = .c_ulonglong },
1612 .{ .simple_type = .c_longdouble },
1613 .{ .simple_type = .f16 },
1614 .{ .simple_type = .f32 },
1615 .{ .simple_type = .f64 },
1616 .{ .simple_type = .f80 },
1617 .{ .simple_type = .f128 },
1618 .{ .simple_type = .anyopaque },
1619 .{ .simple_type = .bool },
1620 .{ .simple_type = .void },
1621 .{ .simple_type = .type },
1622 .{ .simple_type = .anyerror },
1623 .{ .simple_type = .comptime_int },
1624 .{ .simple_type = .comptime_float },
1625 .{ .simple_type = .noreturn },
1626 .{ .anyframe_type = .none },
1627 .{ .simple_type = .null },
1628 .{ .simple_type = .undefined },
1629 .{ .simple_type = .enum_literal },
1630 .{ .simple_type = .atomic_order },
1631 .{ .simple_type = .atomic_rmw_op },
1632 .{ .simple_type = .calling_convention },
1633 .{ .simple_type = .address_space },
1634 .{ .simple_type = .float_mode },
1635 .{ .simple_type = .reduce_op },
1636 .{ .simple_type = .call_modifier },
1637 .{ .simple_type = .prefetch_options },
1638 .{ .simple_type = .export_options },
1639 .{ .simple_type = .extern_options },
1640 .{ .simple_type = .type_info },
1641
1642 .{ .ptr_type = .{
1643 .child = .u8_type,
1644 .flags = .{
1645 .size = .Many,
1646 },
1647 } },
1648
1649 // manyptr_const_u8_type
1650 .{ .ptr_type = .{
1651 .child = .u8_type,
1652 .flags = .{
1653 .size = .Many,
1654 .is_const = true,
1655 },
1656 } },
1657
1658 // manyptr_const_u8_sentinel_0_type
1659 .{ .ptr_type = .{
1660 .child = .u8_type,
1661 .sentinel = .zero_u8,
1662 .flags = .{
1663 .size = .Many,
1664 .is_const = true,
1665 },
1666 } },
1667
1668 .{ .ptr_type = .{
1669 .child = .comptime_int_type,
1670 .flags = .{
1671 .size = .One,
1672 .is_const = true,
1673 },
1674 } },
1675
1676 // slice_const_u8_type
1677 .{ .ptr_type = .{
1678 .child = .u8_type,
1679 .flags = .{
1680 .size = .Slice,
1681 .is_const = true,
1682 },
1683 } },
1684
1685 // slice_const_u8_sentinel_0_type
1686 .{ .ptr_type = .{
1687 .child = .u8_type,
1688 .sentinel = .zero_u8,
1689 .flags = .{
1690 .size = .Slice,
1691 .is_const = true,
1692 },
1693 } },
1694
1695 // anyerror_void_error_union_type
1696 .{ .error_union_type = .{
1697 .error_set_type = .anyerror_type,
1698 .payload_type = .void_type,
1699 } },
1700
1701 // generic_poison_type
1702 .{ .simple_type = .generic_poison },
1703
1704 // empty_struct_type
1705 .{ .anon_struct_type = .{
1706 .types = &.{},
1707 .names = &.{},
1708 .values = &.{},
1709 } },
1710
1711 .{ .simple_value = .undefined },
1712
1713 .{ .int = .{
1714 .ty = .comptime_int_type,
1715 .storage = .{ .u64 = 0 },
1716 } },
1717
1718 .{ .int = .{
1719 .ty = .usize_type,
1720 .storage = .{ .u64 = 0 },
1721 } },
1722
1723 .{ .int = .{
1724 .ty = .u8_type,
1725 .storage = .{ .u64 = 0 },
1726 } },
1727
1728 .{ .int = .{
1729 .ty = .comptime_int_type,
1730 .storage = .{ .u64 = 1 },
1731 } },
1732
1733 .{ .int = .{
1734 .ty = .usize_type,
1735 .storage = .{ .u64 = 1 },
1736 } },
1737
1738 // one_u8
1739 .{ .int = .{
1740 .ty = .u8_type,
1741 .storage = .{ .u64 = 1 },
1742 } },
1743 // four_u8
1744 .{ .int = .{
1745 .ty = .u8_type,
1746 .storage = .{ .u64 = 4 },
1747 } },
1748 // negative_one
1749 .{ .int = .{
1750 .ty = .comptime_int_type,
1751 .storage = .{ .i64 = -1 },
1752 } },
1753 // calling_convention_c
1754 .{ .enum_tag = .{
1755 .ty = .calling_convention_type,
1756 .int = .one_u8,
1757 } },
1758 // calling_convention_inline
1759 .{ .enum_tag = .{
1760 .ty = .calling_convention_type,
1761 .int = .four_u8,
1762 } },
1763
1764 .{ .simple_value = .void },
1765 .{ .simple_value = .@"unreachable" },
1766 .{ .simple_value = .null },
1767 .{ .simple_value = .true },
1768 .{ .simple_value = .false },
1769 .{ .simple_value = .empty_struct },
1770 .{ .simple_value = .generic_poison },
1771};
1772
1773/// How many items in the InternPool are statically known.
1774pub const static_len: u32 = static_keys.len;
1775
1776pub const Tag = enum(u8) {
1777 /// An integer type.
1778 /// data is number of bits
1779 type_int_signed,
1780 /// An integer type.
1781 /// data is number of bits
1782 type_int_unsigned,
1783 /// An array type whose length requires 64 bits or which has a sentinel.
1784 /// data is payload to Array.
1785 type_array_big,
1786 /// An array type that has no sentinel and whose length fits in 32 bits.
1787 /// data is payload to Vector.
1788 type_array_small,
1789 /// A vector type.
1790 /// data is payload to Vector.
1791 type_vector,
1792 /// A fully explicitly specified pointer type.
1793 type_pointer,
1794 /// A slice type.
1795 /// data is Index of underlying pointer type.
1796 type_slice,
1797 /// An optional type.
1798 /// data is the child type.
1799 type_optional,
1800 /// The type `anyframe->T`.
1801 /// data is the child type.
1802 /// If the child type is `none`, the type is `anyframe`.
1803 type_anyframe,
1804 /// An error union type.
1805 /// data is payload to `Key.ErrorUnionType`.
1806 type_error_union,
1807 /// An error set type.
1808 /// data is payload to `ErrorSet`.
1809 type_error_set,
1810 /// The inferred error set type of a function.
1811 /// data is `Module.Fn.InferredErrorSet.Index`.
1812 type_inferred_error_set,
1813 /// An enum type with auto-numbered tag values.
1814 /// The enum is exhaustive.
1815 /// data is payload index to `EnumAuto`.
1816 type_enum_auto,
1817 /// An enum type with an explicitly provided integer tag type.
1818 /// The enum is exhaustive.
1819 /// data is payload index to `EnumExplicit`.
1820 type_enum_explicit,
1821 /// An enum type with an explicitly provided integer tag type.
1822 /// The enum is non-exhaustive.
1823 /// data is payload index to `EnumExplicit`.
1824 type_enum_nonexhaustive,
1825 /// A type that can be represented with only an enum tag.
1826 /// data is SimpleType enum value.
1827 simple_type,
1828 /// An opaque type.
1829 /// data is index of Key.OpaqueType in extra.
1830 type_opaque,
1831 /// A struct type.
1832 /// data is Module.Struct.OptionalIndex
1833 /// The `none` tag is used to represent `@TypeOf(.{})`.
1834 type_struct,
1835 /// A struct type that has only a namespace; no fields, and there is no
1836 /// Module.Struct object allocated for it.
1837 /// data is Module.Namespace.Index.
1838 type_struct_ns,
1839 /// An AnonStructType which stores types, names, and values for fields.
1840 /// data is extra index of `TypeStructAnon`.
1841 type_struct_anon,
1842 /// An AnonStructType which has only types and values for fields.
1843 /// data is extra index of `TypeStructAnon`.
1844 type_tuple_anon,
1845 /// A tagged union type.
1846 /// `data` is `Module.Union.Index`.
1847 type_union_tagged,
1848 /// An untagged union type. It also has no safety tag.
1849 /// `data` is `Module.Union.Index`.
1850 type_union_untagged,
1851 /// An untagged union type which has a safety tag.
1852 /// `data` is `Module.Union.Index`.
1853 type_union_safety,
1854 /// A function body type.
1855 /// `data` is extra index to `TypeFunction`.
1856 type_function,
1857
1858 /// Typed `undefined`.
1859 /// `data` is `Index` of the type.
1860 /// Untyped `undefined` is stored instead via `simple_value`.
1861 undef,
1862 /// A wrapper for values which are comptime-known but should
1863 /// semantically be runtime-known.
1864 /// data is extra index of `TypeValue`.
1865 runtime_value,
1866 /// A value that can be represented with only an enum tag.
1867 /// data is SimpleValue enum value.
1868 simple_value,
1869 /// A pointer to a decl.
1870 /// data is extra index of `PtrDecl`, which contains the type and address.
1871 ptr_decl,
1872 /// A pointer to a decl that can be mutated at comptime.
1873 /// data is extra index of `PtrMutDecl`, which contains the type and address.
1874 ptr_mut_decl,
1875 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
1876 ptr_comptime_field,
1877 /// A pointer with an integer value.
1878 /// data is extra index of `PtrBase`, which contains the type and address.
1879 /// Only pointer types are allowed to have this encoding. Optional types must use
1880 /// `opt_payload` or `opt_null`.
1881 ptr_int,
1882 /// A pointer to the payload of an error union.
1883 /// data is extra index of `PtrBase`, which contains the type and base pointer.
1884 ptr_eu_payload,
1885 /// A pointer to the payload of an optional.
1886 /// data is extra index of `PtrBase`, which contains the type and base pointer.
1887 ptr_opt_payload,
1888 /// A pointer to an array element.
1889 /// data is extra index of PtrBaseIndex, which contains the base array and element index.
1890 /// In order to use this encoding, one must ensure that the `InternPool`
1891 /// already contains the elem pointer type corresponding to this payload.
1892 ptr_elem,
1893 /// A pointer to a container field.
1894 /// data is extra index of PtrBaseIndex, which contains the base container and field index.
1895 ptr_field,
1896 /// A slice.
1897 /// data is extra index of PtrSlice, which contains the ptr and len values
1898 ptr_slice,
1899 /// An optional value that is non-null.
1900 /// data is extra index of `TypeValue`.
1901 /// The type is the optional type (not the payload type).
1902 opt_payload,
1903 /// An optional value that is null.
1904 /// data is Index of the optional type.
1905 opt_null,
1906 /// Type: u8
1907 /// data is integer value
1908 int_u8,
1909 /// Type: u16
1910 /// data is integer value
1911 int_u16,
1912 /// Type: u32
1913 /// data is integer value
1914 int_u32,
1915 /// Type: i32
1916 /// data is integer value bitcasted to u32.
1917 int_i32,
1918 /// A usize that fits in 32 bits.
1919 /// data is integer value.
1920 int_usize,
1921 /// A comptime_int that fits in a u32.
1922 /// data is integer value.
1923 int_comptime_int_u32,
1924 /// A comptime_int that fits in an i32.
1925 /// data is integer value bitcasted to u32.
1926 int_comptime_int_i32,
1927 /// An integer value that fits in 32 bits with an explicitly provided type.
1928 /// data is extra index of `IntSmall`.
1929 int_small,
1930 /// A positive integer value.
1931 /// data is a limbs index to `Int`.
1932 int_positive,
1933 /// A negative integer value.
1934 /// data is a limbs index to `Int`.
1935 int_negative,
1936 /// The ABI alignment of a lazy type.
1937 /// data is extra index of `IntLazy`.
1938 int_lazy_align,
1939 /// The ABI size of a lazy type.
1940 /// data is extra index of `IntLazy`.
1941 int_lazy_size,
1942 /// An error value.
1943 /// data is extra index of `Key.Error`.
1944 error_set_error,
1945 /// An error union error.
1946 /// data is extra index of `Key.Error`.
1947 error_union_error,
1948 /// An error union payload.
1949 /// data is extra index of `TypeValue`.
1950 error_union_payload,
1951 /// An enum literal value.
1952 /// data is `NullTerminatedString` of the error name.
1953 enum_literal,
1954 /// An enum tag value.
1955 /// data is extra index of `EnumTag`.
1956 enum_tag,
1957 /// An f16 value.
1958 /// data is float value bitcasted to u16 and zero-extended.
1959 float_f16,
1960 /// An f32 value.
1961 /// data is float value bitcasted to u32.
1962 float_f32,
1963 /// An f64 value.
1964 /// data is extra index to Float64.
1965 float_f64,
1966 /// An f80 value.
1967 /// data is extra index to Float80.
1968 float_f80,
1969 /// An f128 value.
1970 /// data is extra index to Float128.
1971 float_f128,
1972 /// A c_longdouble value of 80 bits.
1973 /// data is extra index to Float80.
1974 /// This is used when a c_longdouble value is provided as an f80, because f80 has unnormalized
1975 /// values which cannot be losslessly represented as f128. It should only be used when the type
1976 /// underlying c_longdouble for the target is 80 bits.
1977 float_c_longdouble_f80,
1978 /// A c_longdouble value of 128 bits.
1979 /// data is extra index to Float128.
1980 /// This is used when a c_longdouble value is provided as any type other than an f80, since all
1981 /// other float types can be losslessly converted to and from f128.
1982 float_c_longdouble_f128,
1983 /// A comptime_float value.
1984 /// data is extra index to Float128.
1985 float_comptime_float,
1986 /// A global variable.
1987 /// data is extra index to Variable.
1988 variable,
1989 /// An extern function.
1990 /// data is extra index to Key.ExternFunc.
1991 extern_func,
1992 /// A regular function.
1993 /// data is extra index to Func.
1994 func,
1995 /// This represents the only possible value for *some* types which have
1996 /// only one possible value. Not all only-possible-values are encoded this way;
1997 /// for example structs which have all comptime fields are not encoded this way.
1998 /// The set of values that are encoded this way is:
1999 /// * An array or vector which has length 0.
2000 /// * A struct which has all fields comptime-known.
2001 /// * An empty enum or union. TODO: this value's existence is strange, because such a type in reality has no values. See #15909
2002 /// data is Index of the type, which is known to be zero bits at runtime.
2003 only_possible_value,
2004 /// data is extra index to Key.Union.
2005 union_value,
2006 /// An array of bytes.
2007 /// data is extra index to `Bytes`.
2008 bytes,
2009 /// An instance of a struct, array, or vector.
2010 /// data is extra index to `Aggregate`.
2011 aggregate,
2012 /// An instance of an array or vector with every element being the same value.
2013 /// data is extra index to `Repeated`.
2014 repeated,
2015
2016 /// A memoized comptime function call result.
2017 /// data is extra index to `MemoizedCall`
2018 memoized_call,
2019
2020 const ErrorUnionType = Key.ErrorUnionType;
2021 const OpaqueType = Key.OpaqueType;
2022 const TypeValue = Key.TypeValue;
2023 const Error = Key.Error;
2024 const EnumTag = Key.EnumTag;
2025 const ExternFunc = Key.ExternFunc;
2026 const Func = Key.Func;
2027 const Union = Key.Union;
2028 const TypePointer = Key.PtrType;
2029
2030 fn Payload(comptime tag: Tag) type {
2031 return switch (tag) {
2032 .type_int_signed => unreachable,
2033 .type_int_unsigned => unreachable,
2034 .type_array_big => Array,
2035 .type_array_small => Vector,
2036 .type_vector => Vector,
2037 .type_pointer => TypePointer,
2038 .type_slice => unreachable,
2039 .type_optional => unreachable,
2040 .type_anyframe => unreachable,
2041 .type_error_union => ErrorUnionType,
2042 .type_error_set => ErrorSet,
2043 .type_inferred_error_set => unreachable,
2044 .type_enum_auto => EnumAuto,
2045 .type_enum_explicit => EnumExplicit,
2046 .type_enum_nonexhaustive => EnumExplicit,
2047 .simple_type => unreachable,
2048 .type_opaque => OpaqueType,
2049 .type_struct => unreachable,
2050 .type_struct_ns => unreachable,
2051 .type_struct_anon => TypeStructAnon,
2052 .type_tuple_anon => TypeStructAnon,
2053 .type_union_tagged => unreachable,
2054 .type_union_untagged => unreachable,
2055 .type_union_safety => unreachable,
2056 .type_function => TypeFunction,
2057
2058 .undef => unreachable,
2059 .runtime_value => TypeValue,
2060 .simple_value => unreachable,
2061 .ptr_decl => PtrDecl,
2062 .ptr_mut_decl => PtrMutDecl,
2063 .ptr_comptime_field => PtrComptimeField,
2064 .ptr_int => PtrBase,
2065 .ptr_eu_payload => PtrBase,
2066 .ptr_opt_payload => PtrBase,
2067 .ptr_elem => PtrBaseIndex,
2068 .ptr_field => PtrBaseIndex,
2069 .ptr_slice => PtrSlice,
2070 .opt_payload => TypeValue,
2071 .opt_null => unreachable,
2072 .int_u8 => unreachable,
2073 .int_u16 => unreachable,
2074 .int_u32 => unreachable,
2075 .int_i32 => unreachable,
2076 .int_usize => unreachable,
2077 .int_comptime_int_u32 => unreachable,
2078 .int_comptime_int_i32 => unreachable,
2079 .int_small => IntSmall,
2080 .int_positive => unreachable,
2081 .int_negative => unreachable,
2082 .int_lazy_align => IntLazy,
2083 .int_lazy_size => IntLazy,
2084 .error_set_error => Error,
2085 .error_union_error => Error,
2086 .error_union_payload => TypeValue,
2087 .enum_literal => unreachable,
2088 .enum_tag => EnumTag,
2089 .float_f16 => unreachable,
2090 .float_f32 => unreachable,
2091 .float_f64 => unreachable,
2092 .float_f80 => unreachable,
2093 .float_f128 => unreachable,
2094 .float_c_longdouble_f80 => unreachable,
2095 .float_c_longdouble_f128 => unreachable,
2096 .float_comptime_float => unreachable,
2097 .variable => Variable,
2098 .extern_func => ExternFunc,
2099 .func => Func,
2100 .only_possible_value => unreachable,
2101 .union_value => Union,
2102 .bytes => Bytes,
2103 .aggregate => Aggregate,
2104 .repeated => Repeated,
2105 .memoized_call => MemoizedCall,
2106 };
2107 }
2108
2109 pub const Variable = struct {
2110 ty: Index,
2111 /// May be `none`.
2112 init: Index,
2113 decl: Module.Decl.Index,
2114 /// Library name if specified.
2115 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
2116 lib_name: OptionalNullTerminatedString,
2117 flags: Flags,
2118
2119 pub const Flags = packed struct(u32) {
2120 is_extern: bool,
2121 is_const: bool,
2122 is_threadlocal: bool,
2123 is_weak_linkage: bool,
2124 _: u28 = 0,
2125 };
2126 };
2127
2128 /// Trailing:
2129 /// 0. element: Index for each len
2130 /// len is determined by the aggregate type.
2131 pub const Aggregate = struct {
2132 /// The type of the aggregate.
2133 ty: Index,
2134 };
2135};
2136
2137/// Trailing:
2138/// 0. name: NullTerminatedString for each names_len
2139pub const ErrorSet = struct {
2140 names_len: u32,
2141 /// Maps error names to declaration index.
2142 names_map: MapIndex,
2143};
2144
2145/// Trailing:
2146/// 0. param_type: Index for each params_len
2147pub const TypeFunction = struct {
2148 params_len: u32,
2149 return_type: Index,
2150 comptime_bits: u32,
2151 noalias_bits: u32,
2152 flags: Flags,
2153
2154 pub const Flags = packed struct(u32) {
2155 alignment: Alignment,
2156 cc: std.builtin.CallingConvention,
2157 is_var_args: bool,
2158 is_generic: bool,
2159 is_noinline: bool,
2160 align_is_generic: bool,
2161 cc_is_generic: bool,
2162 section_is_generic: bool,
2163 addrspace_is_generic: bool,
2164 _: u11 = 0,
2165 };
2166};
2167
2168pub const Bytes = struct {
2169 /// The type of the aggregate
2170 ty: Index,
2171 /// Index into string_bytes, of len ip.aggregateTypeLen(ty)
2172 bytes: String,
2173};
2174
2175pub const Repeated = struct {
2176 /// The type of the aggregate.
2177 ty: Index,
2178 /// The value of every element.
2179 elem_val: Index,
2180};
2181
2182/// Trailing:
2183/// 0. type: Index for each fields_len
2184/// 1. value: Index for each fields_len
2185/// 2. name: NullTerminatedString for each fields_len
2186/// The set of field names is omitted when the `Tag` is `type_tuple_anon`.
2187pub const TypeStructAnon = struct {
2188 fields_len: u32,
2189};
2190
2191/// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to
2192/// implement logic that only wants to deal with types because the logic can
2193/// ignore all simple values. Note that technically, types are values.
2194pub const SimpleType = enum(u32) {
2195 f16,
2196 f32,
2197 f64,
2198 f80,
2199 f128,
2200 usize,
2201 isize,
2202 c_char,
2203 c_short,
2204 c_ushort,
2205 c_int,
2206 c_uint,
2207 c_long,
2208 c_ulong,
2209 c_longlong,
2210 c_ulonglong,
2211 c_longdouble,
2212 anyopaque,
2213 bool,
2214 void,
2215 type,
2216 anyerror,
2217 comptime_int,
2218 comptime_float,
2219 noreturn,
2220 null,
2221 undefined,
2222 enum_literal,
2223
2224 atomic_order,
2225 atomic_rmw_op,
2226 calling_convention,
2227 address_space,
2228 float_mode,
2229 reduce_op,
2230 call_modifier,
2231 prefetch_options,
2232 export_options,
2233 extern_options,
2234 type_info,
2235
2236 generic_poison,
2237};
2238
2239pub const SimpleValue = enum(u32) {
2240 /// This is untyped `undefined`.
2241 undefined,
2242 void,
2243 /// This is untyped `null`.
2244 null,
2245 /// This is the untyped empty struct literal: `.{}`
2246 empty_struct,
2247 true,
2248 false,
2249 @"unreachable",
2250
2251 generic_poison,
2252};
2253
2254/// Stored as a power-of-two, with one special value to indicate none.
2255pub const Alignment = enum(u6) {
2256 none = std.math.maxInt(u6),
2257 _,
2258
2259 pub fn toByteUnitsOptional(a: Alignment) ?u64 {
2260 return switch (a) {
2261 .none => null,
2262 _ => @as(u64, 1) << @enumToInt(a),
2263 };
2264 }
2265
2266 pub fn toByteUnits(a: Alignment, default: u64) u64 {
2267 return switch (a) {
2268 .none => default,
2269 _ => @as(u64, 1) << @enumToInt(a),
2270 };
2271 }
2272
2273 pub fn fromByteUnits(n: u64) Alignment {
2274 if (n == 0) return .none;
2275 assert(std.math.isPowerOfTwo(n));
2276 return @intToEnum(Alignment, @ctz(n));
2277 }
2278
2279 pub fn fromNonzeroByteUnits(n: u64) Alignment {
2280 assert(n != 0);
2281 return fromByteUnits(n);
2282 }
2283
2284 pub fn min(a: Alignment, b: Alignment) Alignment {
2285 return @intToEnum(Alignment, @min(@enumToInt(a), @enumToInt(b)));
2286 }
2287};
2288
2289/// Used for non-sentineled arrays that have length fitting in u32, as well as
2290/// vectors.
2291pub const Vector = struct {
2292 len: u32,
2293 child: Index,
2294};
2295
2296pub const Array = struct {
2297 len0: u32,
2298 len1: u32,
2299 child: Index,
2300 sentinel: Index,
2301
2302 pub const Length = PackedU64;
2303
2304 pub fn getLength(a: Array) u64 {
2305 return (PackedU64{
2306 .a = a.len0,
2307 .b = a.len1,
2308 }).get();
2309 }
2310};
2311
2312/// Trailing:
2313/// 0. field name: NullTerminatedString for each fields_len; declaration order
2314/// 1. tag value: Index for each fields_len; declaration order
2315pub const EnumExplicit = struct {
2316 /// The Decl that corresponds to the enum itself.
2317 decl: Module.Decl.Index,
2318 /// This may be `none` if there are no declarations.
2319 namespace: Module.Namespace.OptionalIndex,
2320 /// An integer type which is used for the numerical value of the enum, which
2321 /// has been explicitly provided by the enum declaration.
2322 int_tag_type: Index,
2323 fields_len: u32,
2324 /// Maps field names to declaration index.
2325 names_map: MapIndex,
2326 /// Maps field values to declaration index.
2327 /// If this is `none`, it means the trailing tag values are absent because
2328 /// they are auto-numbered.
2329 values_map: OptionalMapIndex,
2330};
2331
2332/// Trailing:
2333/// 0. field name: NullTerminatedString for each fields_len; declaration order
2334pub const EnumAuto = struct {
2335 /// The Decl that corresponds to the enum itself.
2336 decl: Module.Decl.Index,
2337 /// This may be `none` if there are no declarations.
2338 namespace: Module.Namespace.OptionalIndex,
2339 /// An integer type which is used for the numerical value of the enum, which
2340 /// was inferred by Zig based on the number of tags.
2341 int_tag_type: Index,
2342 fields_len: u32,
2343 /// Maps field names to declaration index.
2344 names_map: MapIndex,
2345};
2346
2347pub const PackedU64 = packed struct(u64) {
2348 a: u32,
2349 b: u32,
2350
2351 pub fn get(x: PackedU64) u64 {
2352 return @bitCast(u64, x);
2353 }
2354
2355 pub fn init(x: u64) PackedU64 {
2356 return @bitCast(PackedU64, x);
2357 }
2358};
2359
2360pub const PtrDecl = struct {
2361 ty: Index,
2362 decl: Module.Decl.Index,
2363};
2364
2365pub const PtrMutDecl = struct {
2366 ty: Index,
2367 decl: Module.Decl.Index,
2368 runtime_index: RuntimeIndex,
2369};
2370
2371pub const PtrComptimeField = struct {
2372 ty: Index,
2373 field_val: Index,
2374};
2375
2376pub const PtrBase = struct {
2377 ty: Index,
2378 base: Index,
2379};
2380
2381pub const PtrBaseIndex = struct {
2382 ty: Index,
2383 base: Index,
2384 index: Index,
2385};
2386
2387pub const PtrSlice = struct {
2388 /// The slice type.
2389 ty: Index,
2390 /// A many pointer value.
2391 ptr: Index,
2392 /// A usize value.
2393 len: Index,
2394};
2395
2396/// Trailing: Limb for every limbs_len
2397pub const Int = struct {
2398 ty: Index,
2399 limbs_len: u32,
2400};
2401
2402pub const IntSmall = struct {
2403 ty: Index,
2404 value: u32,
2405};
2406
2407pub const IntLazy = struct {
2408 ty: Index,
2409 lazy_ty: Index,
2410};
2411
2412/// A f64 value, broken up into 2 u32 parts.
2413pub const Float64 = struct {
2414 piece0: u32,
2415 piece1: u32,
2416
2417 pub fn get(self: Float64) f64 {
2418 const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32);
2419 return @bitCast(f64, int_bits);
2420 }
2421
2422 fn pack(val: f64) Float64 {
2423 const bits = @bitCast(u64, val);
2424 return .{
2425 .piece0 = @truncate(u32, bits),
2426 .piece1 = @truncate(u32, bits >> 32),
2427 };
2428 }
2429};
2430
2431/// A f80 value, broken up into 2 u32 parts and a u16 part zero-padded to a u32.
2432pub const Float80 = struct {
2433 piece0: u32,
2434 piece1: u32,
2435 piece2: u32, // u16 part, top bits
2436
2437 pub fn get(self: Float80) f80 {
2438 const int_bits = @as(u80, self.piece0) |
2439 (@as(u80, self.piece1) << 32) |
2440 (@as(u80, self.piece2) << 64);
2441 return @bitCast(f80, int_bits);
2442 }
2443
2444 fn pack(val: f80) Float80 {
2445 const bits = @bitCast(u80, val);
2446 return .{
2447 .piece0 = @truncate(u32, bits),
2448 .piece1 = @truncate(u32, bits >> 32),
2449 .piece2 = @truncate(u16, bits >> 64),
2450 };
2451 }
2452};
2453
2454/// A f128 value, broken up into 4 u32 parts.
2455pub const Float128 = struct {
2456 piece0: u32,
2457 piece1: u32,
2458 piece2: u32,
2459 piece3: u32,
2460
2461 pub fn get(self: Float128) f128 {
2462 const int_bits = @as(u128, self.piece0) |
2463 (@as(u128, self.piece1) << 32) |
2464 (@as(u128, self.piece2) << 64) |
2465 (@as(u128, self.piece3) << 96);
2466 return @bitCast(f128, int_bits);
2467 }
2468
2469 fn pack(val: f128) Float128 {
2470 const bits = @bitCast(u128, val);
2471 return .{
2472 .piece0 = @truncate(u32, bits),
2473 .piece1 = @truncate(u32, bits >> 32),
2474 .piece2 = @truncate(u32, bits >> 64),
2475 .piece3 = @truncate(u32, bits >> 96),
2476 };
2477 }
2478};
2479
2480/// Trailing:
2481/// 0. arg value: Index for each args_len
2482pub const MemoizedCall = struct {
2483 func: Module.Fn.Index,
2484 args_len: u32,
2485 result: Index,
2486};
2487
2488pub fn init(ip: *InternPool, gpa: Allocator) !void {
2489 assert(ip.items.len == 0);
2490
2491 // Reserve string index 0 for an empty string.
2492 assert((try ip.getOrPutString(gpa, "")) == .empty);
2493
2494 // So that we can use `catch unreachable` below.
2495 try ip.items.ensureUnusedCapacity(gpa, static_keys.len);
2496 try ip.map.ensureUnusedCapacity(gpa, static_keys.len);
2497 try ip.extra.ensureUnusedCapacity(gpa, static_keys.len);
2498
2499 // This inserts all the statically-known values into the intern pool in the
2500 // order expected.
2501 for (static_keys) |key| _ = ip.get(gpa, key) catch unreachable;
2502
2503 if (std.debug.runtime_safety) {
2504 // Sanity check.
2505 assert(ip.indexToKey(.bool_true).simple_value == .true);
2506 assert(ip.indexToKey(.bool_false).simple_value == .false);
2507
2508 const cc_inline = ip.indexToKey(.calling_convention_inline).enum_tag.int;
2509 const cc_c = ip.indexToKey(.calling_convention_c).enum_tag.int;
2510
2511 assert(ip.indexToKey(cc_inline).int.storage.u64 ==
2512 @enumToInt(std.builtin.CallingConvention.Inline));
2513
2514 assert(ip.indexToKey(cc_c).int.storage.u64 ==
2515 @enumToInt(std.builtin.CallingConvention.C));
2516
2517 assert(ip.indexToKey(ip.typeOf(cc_inline)).int_type.bits ==
2518 @typeInfo(@typeInfo(std.builtin.CallingConvention).Enum.tag_type).Int.bits);
2519 }
2520
2521 assert(ip.items.len == static_keys.len);
2522}
2523
2524pub fn deinit(ip: *InternPool, gpa: Allocator) void {
2525 ip.map.deinit(gpa);
2526 ip.items.deinit(gpa);
2527 ip.extra.deinit(gpa);
2528 ip.limbs.deinit(gpa);
2529 ip.string_bytes.deinit(gpa);
2530
2531 ip.structs_free_list.deinit(gpa);
2532 ip.allocated_structs.deinit(gpa);
2533
2534 ip.unions_free_list.deinit(gpa);
2535 ip.allocated_unions.deinit(gpa);
2536
2537 ip.funcs_free_list.deinit(gpa);
2538 ip.allocated_funcs.deinit(gpa);
2539
2540 ip.inferred_error_sets_free_list.deinit(gpa);
2541 ip.allocated_inferred_error_sets.deinit(gpa);
2542
2543 for (ip.maps.items) |*map| map.deinit(gpa);
2544 ip.maps.deinit(gpa);
2545
2546 ip.string_table.deinit(gpa);
2547
2548 ip.* = undefined;
2549}
2550
2551pub fn indexToKey(ip: *const InternPool, index: Index) Key {
2552 assert(index != .none);
2553 const item = ip.items.get(@enumToInt(index));
2554 const data = item.data;
2555 return switch (item.tag) {
2556 .type_int_signed => .{
2557 .int_type = .{
2558 .signedness = .signed,
2559 .bits = @intCast(u16, data),
2560 },
2561 },
2562 .type_int_unsigned => .{
2563 .int_type = .{
2564 .signedness = .unsigned,
2565 .bits = @intCast(u16, data),
2566 },
2567 },
2568 .type_array_big => {
2569 const array_info = ip.extraData(Array, data);
2570 return .{ .array_type = .{
2571 .len = array_info.getLength(),
2572 .child = array_info.child,
2573 .sentinel = array_info.sentinel,
2574 } };
2575 },
2576 .type_array_small => {
2577 const array_info = ip.extraData(Vector, data);
2578 return .{ .array_type = .{
2579 .len = array_info.len,
2580 .child = array_info.child,
2581 .sentinel = .none,
2582 } };
2583 },
2584 .simple_type => .{ .simple_type = @intToEnum(SimpleType, data) },
2585 .simple_value => .{ .simple_value = @intToEnum(SimpleValue, data) },
2586
2587 .type_vector => {
2588 const vector_info = ip.extraData(Vector, data);
2589 return .{ .vector_type = .{
2590 .len = vector_info.len,
2591 .child = vector_info.child,
2592 } };
2593 },
2594
2595 .type_pointer => .{ .ptr_type = ip.extraData(Tag.TypePointer, data) },
2596
2597 .type_slice => {
2598 assert(ip.items.items(.tag)[data] == .type_pointer);
2599 var ptr_info = ip.extraData(Tag.TypePointer, ip.items.items(.data)[data]);
2600 ptr_info.flags.size = .Slice;
2601 return .{ .ptr_type = ptr_info };
2602 },
2603
2604 .type_optional => .{ .opt_type = @intToEnum(Index, data) },
2605 .type_anyframe => .{ .anyframe_type = @intToEnum(Index, data) },
2606
2607 .type_error_union => .{ .error_union_type = ip.extraData(Key.ErrorUnionType, data) },
2608 .type_error_set => {
2609 const error_set = ip.extraDataTrail(ErrorSet, data);
2610 const names_len = error_set.data.names_len;
2611 const names = ip.extra.items[error_set.end..][0..names_len];
2612 return .{ .error_set_type = .{
2613 .names = @ptrCast([]const NullTerminatedString, names),
2614 .names_map = error_set.data.names_map.toOptional(),
2615 } };
2616 },
2617 .type_inferred_error_set => .{
2618 .inferred_error_set_type = @intToEnum(Module.Fn.InferredErrorSet.Index, data),
2619 },
2620
2621 .type_opaque => .{ .opaque_type = ip.extraData(Key.OpaqueType, data) },
2622 .type_struct => {
2623 const struct_index = @intToEnum(Module.Struct.OptionalIndex, data);
2624 const namespace = if (struct_index.unwrap()) |i|
2625 ip.structPtrConst(i).namespace.toOptional()
2626 else
2627 .none;
2628 return .{ .struct_type = .{
2629 .index = struct_index,
2630 .namespace = namespace,
2631 } };
2632 },
2633 .type_struct_ns => .{ .struct_type = .{
2634 .index = .none,
2635 .namespace = @intToEnum(Module.Namespace.Index, data).toOptional(),
2636 } },
2637
2638 .type_struct_anon => {
2639 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
2640 const fields_len = type_struct_anon.data.fields_len;
2641 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
2642 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2643 const names = ip.extra.items[type_struct_anon.end + 2 * fields_len ..][0..fields_len];
2644 return .{ .anon_struct_type = .{
2645 .types = @ptrCast([]const Index, types),
2646 .values = @ptrCast([]const Index, values),
2647 .names = @ptrCast([]const NullTerminatedString, names),
2648 } };
2649 },
2650 .type_tuple_anon => {
2651 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, data);
2652 const fields_len = type_struct_anon.data.fields_len;
2653 const types = ip.extra.items[type_struct_anon.end..][0..fields_len];
2654 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2655 return .{ .anon_struct_type = .{
2656 .types = @ptrCast([]const Index, types),
2657 .values = @ptrCast([]const Index, values),
2658 .names = &.{},
2659 } };
2660 },
2661
2662 .type_union_untagged => .{ .union_type = .{
2663 .index = @intToEnum(Module.Union.Index, data),
2664 .runtime_tag = .none,
2665 } },
2666 .type_union_tagged => .{ .union_type = .{
2667 .index = @intToEnum(Module.Union.Index, data),
2668 .runtime_tag = .tagged,
2669 } },
2670 .type_union_safety => .{ .union_type = .{
2671 .index = @intToEnum(Module.Union.Index, data),
2672 .runtime_tag = .safety,
2673 } },
2674
2675 .type_enum_auto => {
2676 const enum_auto = ip.extraDataTrail(EnumAuto, data);
2677 const names = @ptrCast(
2678 []const NullTerminatedString,
2679 ip.extra.items[enum_auto.end..][0..enum_auto.data.fields_len],
2680 );
2681 return .{ .enum_type = .{
2682 .decl = enum_auto.data.decl,
2683 .namespace = enum_auto.data.namespace,
2684 .tag_ty = enum_auto.data.int_tag_type,
2685 .names = names,
2686 .values = &.{},
2687 .tag_mode = .auto,
2688 .names_map = enum_auto.data.names_map.toOptional(),
2689 .values_map = .none,
2690 } };
2691 },
2692 .type_enum_explicit => ip.indexToKeyEnum(data, .explicit),
2693 .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive),
2694 .type_function => .{ .func_type = ip.indexToKeyFuncType(data) },
2695
2696 .undef => .{ .undef = @intToEnum(Index, data) },
2697 .runtime_value => .{ .runtime_value = ip.extraData(Tag.TypeValue, data) },
2698 .opt_null => .{ .opt = .{
2699 .ty = @intToEnum(Index, data),
2700 .val = .none,
2701 } },
2702 .opt_payload => {
2703 const extra = ip.extraData(Tag.TypeValue, data);
2704 return .{ .opt = .{
2705 .ty = extra.ty,
2706 .val = extra.val,
2707 } };
2708 },
2709 .ptr_decl => {
2710 const info = ip.extraData(PtrDecl, data);
2711 return .{ .ptr = .{
2712 .ty = info.ty,
2713 .addr = .{ .decl = info.decl },
2714 } };
2715 },
2716 .ptr_mut_decl => {
2717 const info = ip.extraData(PtrMutDecl, data);
2718 return .{ .ptr = .{
2719 .ty = info.ty,
2720 .addr = .{ .mut_decl = .{
2721 .decl = info.decl,
2722 .runtime_index = info.runtime_index,
2723 } },
2724 } };
2725 },
2726 .ptr_comptime_field => {
2727 const info = ip.extraData(PtrComptimeField, data);
2728 return .{ .ptr = .{
2729 .ty = info.ty,
2730 .addr = .{ .comptime_field = info.field_val },
2731 } };
2732 },
2733 .ptr_int => {
2734 const info = ip.extraData(PtrBase, data);
2735 return .{ .ptr = .{
2736 .ty = info.ty,
2737 .addr = .{ .int = info.base },
2738 } };
2739 },
2740 .ptr_eu_payload => {
2741 const info = ip.extraData(PtrBase, data);
2742 return .{ .ptr = .{
2743 .ty = info.ty,
2744 .addr = .{ .eu_payload = info.base },
2745 } };
2746 },
2747 .ptr_opt_payload => {
2748 const info = ip.extraData(PtrBase, data);
2749 return .{ .ptr = .{
2750 .ty = info.ty,
2751 .addr = .{ .opt_payload = info.base },
2752 } };
2753 },
2754 .ptr_elem => {
2755 // Avoid `indexToKey` recursion by asserting the tag encoding.
2756 const info = ip.extraData(PtrBaseIndex, data);
2757 const index_item = ip.items.get(@enumToInt(info.index));
2758 return switch (index_item.tag) {
2759 .int_usize => .{ .ptr = .{
2760 .ty = info.ty,
2761 .addr = .{ .elem = .{
2762 .base = info.base,
2763 .index = index_item.data,
2764 } },
2765 } },
2766 .int_positive => @panic("TODO"), // implement along with behavior test coverage
2767 else => unreachable,
2768 };
2769 },
2770 .ptr_field => {
2771 // Avoid `indexToKey` recursion by asserting the tag encoding.
2772 const info = ip.extraData(PtrBaseIndex, data);
2773 const index_item = ip.items.get(@enumToInt(info.index));
2774 return switch (index_item.tag) {
2775 .int_usize => .{ .ptr = .{
2776 .ty = info.ty,
2777 .addr = .{ .field = .{
2778 .base = info.base,
2779 .index = index_item.data,
2780 } },
2781 } },
2782 .int_positive => @panic("TODO"), // implement along with behavior test coverage
2783 else => unreachable,
2784 };
2785 },
2786 .ptr_slice => {
2787 const info = ip.extraData(PtrSlice, data);
2788 const ptr_item = ip.items.get(@enumToInt(info.ptr));
2789 return .{
2790 .ptr = .{
2791 .ty = info.ty,
2792 .addr = switch (ptr_item.tag) {
2793 .ptr_decl => .{
2794 .decl = ip.extraData(PtrDecl, ptr_item.data).decl,
2795 },
2796 .ptr_mut_decl => b: {
2797 const sub_info = ip.extraData(PtrMutDecl, ptr_item.data);
2798 break :b .{ .mut_decl = .{
2799 .decl = sub_info.decl,
2800 .runtime_index = sub_info.runtime_index,
2801 } };
2802 },
2803 .ptr_comptime_field => .{
2804 .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val,
2805 },
2806 .ptr_int => .{
2807 .int = ip.extraData(PtrBase, ptr_item.data).base,
2808 },
2809 .ptr_eu_payload => .{
2810 .eu_payload = ip.extraData(PtrBase, ptr_item.data).base,
2811 },
2812 .ptr_opt_payload => .{
2813 .opt_payload = ip.extraData(PtrBase, ptr_item.data).base,
2814 },
2815 .ptr_elem => b: {
2816 // Avoid `indexToKey` recursion by asserting the tag encoding.
2817 const sub_info = ip.extraData(PtrBaseIndex, ptr_item.data);
2818 const index_item = ip.items.get(@enumToInt(sub_info.index));
2819 break :b switch (index_item.tag) {
2820 .int_usize => .{ .elem = .{
2821 .base = sub_info.base,
2822 .index = index_item.data,
2823 } },
2824 .int_positive => @panic("TODO"), // implement along with behavior test coverage
2825 else => unreachable,
2826 };
2827 },
2828 .ptr_field => b: {
2829 // Avoid `indexToKey` recursion by asserting the tag encoding.
2830 const sub_info = ip.extraData(PtrBaseIndex, ptr_item.data);
2831 const index_item = ip.items.get(@enumToInt(sub_info.index));
2832 break :b switch (index_item.tag) {
2833 .int_usize => .{ .field = .{
2834 .base = sub_info.base,
2835 .index = index_item.data,
2836 } },
2837 .int_positive => @panic("TODO"), // implement along with behavior test coverage
2838 else => unreachable,
2839 };
2840 },
2841 else => unreachable,
2842 },
2843 .len = info.len,
2844 },
2845 };
2846 },
2847 .int_u8 => .{ .int = .{
2848 .ty = .u8_type,
2849 .storage = .{ .u64 = data },
2850 } },
2851 .int_u16 => .{ .int = .{
2852 .ty = .u16_type,
2853 .storage = .{ .u64 = data },
2854 } },
2855 .int_u32 => .{ .int = .{
2856 .ty = .u32_type,
2857 .storage = .{ .u64 = data },
2858 } },
2859 .int_i32 => .{ .int = .{
2860 .ty = .i32_type,
2861 .storage = .{ .i64 = @bitCast(i32, data) },
2862 } },
2863 .int_usize => .{ .int = .{
2864 .ty = .usize_type,
2865 .storage = .{ .u64 = data },
2866 } },
2867 .int_comptime_int_u32 => .{ .int = .{
2868 .ty = .comptime_int_type,
2869 .storage = .{ .u64 = data },
2870 } },
2871 .int_comptime_int_i32 => .{ .int = .{
2872 .ty = .comptime_int_type,
2873 .storage = .{ .i64 = @bitCast(i32, data) },
2874 } },
2875 .int_positive => ip.indexToKeyBigInt(data, true),
2876 .int_negative => ip.indexToKeyBigInt(data, false),
2877 .int_small => {
2878 const info = ip.extraData(IntSmall, data);
2879 return .{ .int = .{
2880 .ty = info.ty,
2881 .storage = .{ .u64 = info.value },
2882 } };
2883 },
2884 .int_lazy_align, .int_lazy_size => |tag| {
2885 const info = ip.extraData(IntLazy, data);
2886 return .{ .int = .{
2887 .ty = info.ty,
2888 .storage = switch (tag) {
2889 .int_lazy_align => .{ .lazy_align = info.lazy_ty },
2890 .int_lazy_size => .{ .lazy_size = info.lazy_ty },
2891 else => unreachable,
2892 },
2893 } };
2894 },
2895 .float_f16 => .{ .float = .{
2896 .ty = .f16_type,
2897 .storage = .{ .f16 = @bitCast(f16, @intCast(u16, data)) },
2898 } },
2899 .float_f32 => .{ .float = .{
2900 .ty = .f32_type,
2901 .storage = .{ .f32 = @bitCast(f32, data) },
2902 } },
2903 .float_f64 => .{ .float = .{
2904 .ty = .f64_type,
2905 .storage = .{ .f64 = ip.extraData(Float64, data).get() },
2906 } },
2907 .float_f80 => .{ .float = .{
2908 .ty = .f80_type,
2909 .storage = .{ .f80 = ip.extraData(Float80, data).get() },
2910 } },
2911 .float_f128 => .{ .float = .{
2912 .ty = .f128_type,
2913 .storage = .{ .f128 = ip.extraData(Float128, data).get() },
2914 } },
2915 .float_c_longdouble_f80 => .{ .float = .{
2916 .ty = .c_longdouble_type,
2917 .storage = .{ .f80 = ip.extraData(Float80, data).get() },
2918 } },
2919 .float_c_longdouble_f128 => .{ .float = .{
2920 .ty = .c_longdouble_type,
2921 .storage = .{ .f128 = ip.extraData(Float128, data).get() },
2922 } },
2923 .float_comptime_float => .{ .float = .{
2924 .ty = .comptime_float_type,
2925 .storage = .{ .f128 = ip.extraData(Float128, data).get() },
2926 } },
2927 .variable => {
2928 const extra = ip.extraData(Tag.Variable, data);
2929 return .{ .variable = .{
2930 .ty = extra.ty,
2931 .init = extra.init,
2932 .decl = extra.decl,
2933 .lib_name = extra.lib_name,
2934 .is_extern = extra.flags.is_extern,
2935 .is_const = extra.flags.is_const,
2936 .is_threadlocal = extra.flags.is_threadlocal,
2937 .is_weak_linkage = extra.flags.is_weak_linkage,
2938 } };
2939 },
2940 .extern_func => .{ .extern_func = ip.extraData(Tag.ExternFunc, data) },
2941 .func => .{ .func = ip.extraData(Tag.Func, data) },
2942 .only_possible_value => {
2943 const ty = @intToEnum(Index, data);
2944 const ty_item = ip.items.get(@enumToInt(ty));
2945 return switch (ty_item.tag) {
2946 .type_array_big => {
2947 const sentinel = @ptrCast(
2948 *const [1]Index,
2949 &ip.extra.items[ty_item.data + std.meta.fieldIndex(Array, "sentinel").?],
2950 );
2951 return .{ .aggregate = .{
2952 .ty = ty,
2953 .storage = .{ .elems = sentinel[0..@boolToInt(sentinel[0] != .none)] },
2954 } };
2955 },
2956 .type_array_small, .type_vector => .{ .aggregate = .{
2957 .ty = ty,
2958 .storage = .{ .elems = &.{} },
2959 } },
2960 // TODO: migrate structs to properly use the InternPool rather
2961 // than using the SegmentedList trick, then the struct type will
2962 // have a slice of comptime values that can be used here for when
2963 // the struct has one possible value due to all fields comptime (same
2964 // as the tuple case below).
2965 .type_struct, .type_struct_ns => .{ .aggregate = .{
2966 .ty = ty,
2967 .storage = .{ .elems = &.{} },
2968 } },
2969
2970 // There is only one possible value precisely due to the
2971 // fact that this values slice is fully populated!
2972 .type_struct_anon, .type_tuple_anon => {
2973 const type_struct_anon = ip.extraDataTrail(TypeStructAnon, ty_item.data);
2974 const fields_len = type_struct_anon.data.fields_len;
2975 const values = ip.extra.items[type_struct_anon.end + fields_len ..][0..fields_len];
2976 return .{ .aggregate = .{
2977 .ty = ty,
2978 .storage = .{ .elems = @ptrCast([]const Index, values) },
2979 } };
2980 },
2981
2982 .type_enum_auto,
2983 .type_enum_explicit,
2984 .type_union_tagged,
2985 .type_union_untagged,
2986 .type_union_safety,
2987 => .{ .empty_enum_value = ty },
2988
2989 else => unreachable,
2990 };
2991 },
2992 .bytes => {
2993 const extra = ip.extraData(Bytes, data);
2994 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(extra.ty));
2995 return .{ .aggregate = .{
2996 .ty = extra.ty,
2997 .storage = .{ .bytes = ip.string_bytes.items[@enumToInt(extra.bytes)..][0..len] },
2998 } };
2999 },
3000 .aggregate => {
3001 const extra = ip.extraDataTrail(Tag.Aggregate, data);
3002 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(extra.data.ty));
3003 const fields = @ptrCast([]const Index, ip.extra.items[extra.end..][0..len]);
3004 return .{ .aggregate = .{
3005 .ty = extra.data.ty,
3006 .storage = .{ .elems = fields },
3007 } };
3008 },
3009 .repeated => {
3010 const extra = ip.extraData(Repeated, data);
3011 return .{ .aggregate = .{
3012 .ty = extra.ty,
3013 .storage = .{ .repeated_elem = extra.elem_val },
3014 } };
3015 },
3016 .union_value => .{ .un = ip.extraData(Key.Union, data) },
3017 .error_set_error => .{ .err = ip.extraData(Key.Error, data) },
3018 .error_union_error => {
3019 const extra = ip.extraData(Key.Error, data);
3020 return .{ .error_union = .{
3021 .ty = extra.ty,
3022 .val = .{ .err_name = extra.name },
3023 } };
3024 },
3025 .error_union_payload => {
3026 const extra = ip.extraData(Tag.TypeValue, data);
3027 return .{ .error_union = .{
3028 .ty = extra.ty,
3029 .val = .{ .payload = extra.val },
3030 } };
3031 },
3032 .enum_literal => .{ .enum_literal = @intToEnum(NullTerminatedString, data) },
3033 .enum_tag => .{ .enum_tag = ip.extraData(Tag.EnumTag, data) },
3034
3035 .memoized_call => {
3036 const extra = ip.extraDataTrail(MemoizedCall, data);
3037 return .{ .memoized_call = .{
3038 .func = extra.data.func,
3039 .arg_values = @ptrCast([]const Index, ip.extra.items[extra.end..][0..extra.data.args_len]),
3040 .result = extra.data.result,
3041 } };
3042 },
3043 };
3044}
3045
3046fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {
3047 const type_function = ip.extraDataTrail(TypeFunction, data);
3048 const param_types = @ptrCast(
3049 []Index,
3050 ip.extra.items[type_function.end..][0..type_function.data.params_len],
3051 );
3052 return .{
3053 .param_types = param_types,
3054 .return_type = type_function.data.return_type,
3055 .comptime_bits = type_function.data.comptime_bits,
3056 .noalias_bits = type_function.data.noalias_bits,
3057 .alignment = type_function.data.flags.alignment,
3058 .cc = type_function.data.flags.cc,
3059 .is_var_args = type_function.data.flags.is_var_args,
3060 .is_generic = type_function.data.flags.is_generic,
3061 .is_noinline = type_function.data.flags.is_noinline,
3062 .align_is_generic = type_function.data.flags.align_is_generic,
3063 .cc_is_generic = type_function.data.flags.cc_is_generic,
3064 .section_is_generic = type_function.data.flags.section_is_generic,
3065 .addrspace_is_generic = type_function.data.flags.addrspace_is_generic,
3066 };
3067}
3068
3069fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
3070 const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
3071 const names = @ptrCast(
3072 []const NullTerminatedString,
3073 ip.extra.items[enum_explicit.end..][0..enum_explicit.data.fields_len],
3074 );
3075 const values = if (enum_explicit.data.values_map != .none) @ptrCast(
3076 []const Index,
3077 ip.extra.items[enum_explicit.end + names.len ..][0..enum_explicit.data.fields_len],
3078 ) else &[0]Index{};
3079
3080 return .{ .enum_type = .{
3081 .decl = enum_explicit.data.decl,
3082 .namespace = enum_explicit.data.namespace,
3083 .tag_ty = enum_explicit.data.int_tag_type,
3084 .names = names,
3085 .values = values,
3086 .tag_mode = tag_mode,
3087 .names_map = enum_explicit.data.names_map.toOptional(),
3088 .values_map = enum_explicit.data.values_map,
3089 } };
3090}
3091
3092fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key {
3093 const int_info = ip.limbData(Int, limb_index);
3094 return .{ .int = .{
3095 .ty = int_info.ty,
3096 .storage = .{ .big_int = .{
3097 .limbs = ip.limbSlice(Int, limb_index, int_info.limbs_len),
3098 .positive = positive,
3099 } },
3100 } };
3101}
3102
3103pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3104 const adapter: KeyAdapter = .{ .intern_pool = ip };
3105 const gop = try ip.map.getOrPutAdapted(gpa, key, adapter);
3106 if (gop.found_existing) return @intToEnum(Index, gop.index);
3107 try ip.items.ensureUnusedCapacity(gpa, 1);
3108 switch (key) {
3109 .int_type => |int_type| {
3110 const t: Tag = switch (int_type.signedness) {
3111 .signed => .type_int_signed,
3112 .unsigned => .type_int_unsigned,
3113 };
3114 ip.items.appendAssumeCapacity(.{
3115 .tag = t,
3116 .data = int_type.bits,
3117 });
3118 },
3119 .ptr_type => |ptr_type| {
3120 assert(ptr_type.child != .none);
3121 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.child);
3122
3123 if (ptr_type.flags.size == .Slice) {
3124 _ = ip.map.pop();
3125 var new_key = key;
3126 new_key.ptr_type.flags.size = .Many;
3127 const ptr_type_index = try ip.get(gpa, new_key);
3128 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3129 try ip.items.ensureUnusedCapacity(gpa, 1);
3130 ip.items.appendAssumeCapacity(.{
3131 .tag = .type_slice,
3132 .data = @enumToInt(ptr_type_index),
3133 });
3134 return @intToEnum(Index, ip.items.len - 1);
3135 }
3136
3137 var ptr_type_adjusted = ptr_type;
3138 if (ptr_type.flags.size == .C) ptr_type_adjusted.flags.is_allowzero = true;
3139
3140 ip.items.appendAssumeCapacity(.{
3141 .tag = .type_pointer,
3142 .data = try ip.addExtra(gpa, ptr_type_adjusted),
3143 });
3144 },
3145 .array_type => |array_type| {
3146 assert(array_type.child != .none);
3147 assert(array_type.sentinel == .none or ip.typeOf(array_type.sentinel) == array_type.child);
3148
3149 if (std.math.cast(u32, array_type.len)) |len| {
3150 if (array_type.sentinel == .none) {
3151 ip.items.appendAssumeCapacity(.{
3152 .tag = .type_array_small,
3153 .data = try ip.addExtra(gpa, Vector{
3154 .len = len,
3155 .child = array_type.child,
3156 }),
3157 });
3158 return @intToEnum(Index, ip.items.len - 1);
3159 }
3160 }
3161
3162 const length = Array.Length.init(array_type.len);
3163 ip.items.appendAssumeCapacity(.{
3164 .tag = .type_array_big,
3165 .data = try ip.addExtra(gpa, Array{
3166 .len0 = length.a,
3167 .len1 = length.b,
3168 .child = array_type.child,
3169 .sentinel = array_type.sentinel,
3170 }),
3171 });
3172 },
3173 .vector_type => |vector_type| {
3174 ip.items.appendAssumeCapacity(.{
3175 .tag = .type_vector,
3176 .data = try ip.addExtra(gpa, Vector{
3177 .len = vector_type.len,
3178 .child = vector_type.child,
3179 }),
3180 });
3181 },
3182 .opt_type => |payload_type| {
3183 assert(payload_type != .none);
3184 ip.items.appendAssumeCapacity(.{
3185 .tag = .type_optional,
3186 .data = @enumToInt(payload_type),
3187 });
3188 },
3189 .anyframe_type => |payload_type| {
3190 // payload_type might be none, indicating the type is `anyframe`.
3191 ip.items.appendAssumeCapacity(.{
3192 .tag = .type_anyframe,
3193 .data = @enumToInt(payload_type),
3194 });
3195 },
3196 .error_union_type => |error_union_type| {
3197 ip.items.appendAssumeCapacity(.{
3198 .tag = .type_error_union,
3199 .data = try ip.addExtra(gpa, error_union_type),
3200 });
3201 },
3202 .error_set_type => |error_set_type| {
3203 assert(error_set_type.names_map == .none);
3204 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names, {}, NullTerminatedString.indexLessThan));
3205 const names_map = try ip.addMap(gpa);
3206 try addStringsToMap(ip, gpa, names_map, error_set_type.names);
3207 const names_len = @intCast(u32, error_set_type.names.len);
3208 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(ErrorSet).Struct.fields.len + names_len);
3209 ip.items.appendAssumeCapacity(.{
3210 .tag = .type_error_set,
3211 .data = ip.addExtraAssumeCapacity(ErrorSet{
3212 .names_len = names_len,
3213 .names_map = names_map,
3214 }),
3215 });
3216 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, error_set_type.names));
3217 },
3218 .inferred_error_set_type => |ies_index| {
3219 ip.items.appendAssumeCapacity(.{
3220 .tag = .type_inferred_error_set,
3221 .data = @enumToInt(ies_index),
3222 });
3223 },
3224 .simple_type => |simple_type| {
3225 ip.items.appendAssumeCapacity(.{
3226 .tag = .simple_type,
3227 .data = @enumToInt(simple_type),
3228 });
3229 },
3230 .simple_value => |simple_value| {
3231 ip.items.appendAssumeCapacity(.{
3232 .tag = .simple_value,
3233 .data = @enumToInt(simple_value),
3234 });
3235 },
3236 .undef => |ty| {
3237 assert(ty != .none);
3238 ip.items.appendAssumeCapacity(.{
3239 .tag = .undef,
3240 .data = @enumToInt(ty),
3241 });
3242 },
3243 .runtime_value => |runtime_value| {
3244 assert(runtime_value.ty == ip.typeOf(runtime_value.val));
3245 ip.items.appendAssumeCapacity(.{
3246 .tag = .runtime_value,
3247 .data = try ip.addExtra(gpa, runtime_value),
3248 });
3249 },
3250
3251 .struct_type => |struct_type| {
3252 ip.items.appendAssumeCapacity(if (struct_type.index.unwrap()) |i| .{
3253 .tag = .type_struct,
3254 .data = @enumToInt(i),
3255 } else if (struct_type.namespace.unwrap()) |i| .{
3256 .tag = .type_struct_ns,
3257 .data = @enumToInt(i),
3258 } else .{
3259 .tag = .type_struct,
3260 .data = @enumToInt(Module.Struct.OptionalIndex.none),
3261 });
3262 },
3263
3264 .anon_struct_type => |anon_struct_type| {
3265 assert(anon_struct_type.types.len == anon_struct_type.values.len);
3266 for (anon_struct_type.types) |elem| assert(elem != .none);
3267
3268 const fields_len = @intCast(u32, anon_struct_type.types.len);
3269 if (anon_struct_type.names.len == 0) {
3270 try ip.extra.ensureUnusedCapacity(
3271 gpa,
3272 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 2),
3273 );
3274 ip.items.appendAssumeCapacity(.{
3275 .tag = .type_tuple_anon,
3276 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
3277 .fields_len = fields_len,
3278 }),
3279 });
3280 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.types));
3281 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.values));
3282 return @intToEnum(Index, ip.items.len - 1);
3283 }
3284
3285 assert(anon_struct_type.names.len == anon_struct_type.types.len);
3286
3287 try ip.extra.ensureUnusedCapacity(
3288 gpa,
3289 @typeInfo(TypeStructAnon).Struct.fields.len + (fields_len * 3),
3290 );
3291 ip.items.appendAssumeCapacity(.{
3292 .tag = .type_struct_anon,
3293 .data = ip.addExtraAssumeCapacity(TypeStructAnon{
3294 .fields_len = fields_len,
3295 }),
3296 });
3297 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.types));
3298 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.values));
3299 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, anon_struct_type.names));
3300 return @intToEnum(Index, ip.items.len - 1);
3301 },
3302
3303 .union_type => |union_type| {
3304 ip.items.appendAssumeCapacity(.{
3305 .tag = switch (union_type.runtime_tag) {
3306 .none => .type_union_untagged,
3307 .safety => .type_union_safety,
3308 .tagged => .type_union_tagged,
3309 },
3310 .data = @enumToInt(union_type.index),
3311 });
3312 },
3313
3314 .opaque_type => |opaque_type| {
3315 ip.items.appendAssumeCapacity(.{
3316 .tag = .type_opaque,
3317 .data = try ip.addExtra(gpa, opaque_type),
3318 });
3319 },
3320
3321 .enum_type => |enum_type| {
3322 assert(enum_type.tag_ty == .noreturn_type or ip.isIntegerType(enum_type.tag_ty));
3323 for (enum_type.values) |value| assert(ip.typeOf(value) == enum_type.tag_ty);
3324 assert(enum_type.names_map == .none);
3325 assert(enum_type.values_map == .none);
3326
3327 switch (enum_type.tag_mode) {
3328 .auto => {
3329 const names_map = try ip.addMap(gpa);
3330 try addStringsToMap(ip, gpa, names_map, enum_type.names);
3331
3332 const fields_len = @intCast(u32, enum_type.names.len);
3333 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumAuto).Struct.fields.len +
3334 fields_len);
3335 ip.items.appendAssumeCapacity(.{
3336 .tag = .type_enum_auto,
3337 .data = ip.addExtraAssumeCapacity(EnumAuto{
3338 .decl = enum_type.decl,
3339 .namespace = enum_type.namespace,
3340 .int_tag_type = enum_type.tag_ty,
3341 .names_map = names_map,
3342 .fields_len = fields_len,
3343 }),
3344 });
3345 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, enum_type.names));
3346 return @intToEnum(Index, ip.items.len - 1);
3347 },
3348 .explicit => return finishGetEnum(ip, gpa, enum_type, .type_enum_explicit),
3349 .nonexhaustive => return finishGetEnum(ip, gpa, enum_type, .type_enum_nonexhaustive),
3350 }
3351 },
3352
3353 .func_type => |func_type| {
3354 assert(func_type.return_type != .none);
3355 for (func_type.param_types) |param_type| assert(param_type != .none);
3356
3357 const params_len = @intCast(u32, func_type.param_types.len);
3358
3359 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(TypeFunction).Struct.fields.len +
3360 params_len);
3361 ip.items.appendAssumeCapacity(.{
3362 .tag = .type_function,
3363 .data = ip.addExtraAssumeCapacity(TypeFunction{
3364 .params_len = params_len,
3365 .return_type = func_type.return_type,
3366 .comptime_bits = func_type.comptime_bits,
3367 .noalias_bits = func_type.noalias_bits,
3368 .flags = .{
3369 .alignment = func_type.alignment,
3370 .cc = func_type.cc,
3371 .is_var_args = func_type.is_var_args,
3372 .is_generic = func_type.is_generic,
3373 .is_noinline = func_type.is_noinline,
3374 .align_is_generic = func_type.align_is_generic,
3375 .cc_is_generic = func_type.cc_is_generic,
3376 .section_is_generic = func_type.section_is_generic,
3377 .addrspace_is_generic = func_type.addrspace_is_generic,
3378 },
3379 }),
3380 });
3381 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, func_type.param_types));
3382 },
3383
3384 .variable => |variable| {
3385 const has_init = variable.init != .none;
3386 if (has_init) assert(variable.ty == ip.typeOf(variable.init));
3387 ip.items.appendAssumeCapacity(.{
3388 .tag = .variable,
3389 .data = try ip.addExtra(gpa, Tag.Variable{
3390 .ty = variable.ty,
3391 .init = variable.init,
3392 .decl = variable.decl,
3393 .lib_name = variable.lib_name,
3394 .flags = .{
3395 .is_extern = variable.is_extern,
3396 .is_const = variable.is_const,
3397 .is_threadlocal = variable.is_threadlocal,
3398 .is_weak_linkage = variable.is_weak_linkage,
3399 },
3400 }),
3401 });
3402 },
3403
3404 .extern_func => |extern_func| ip.items.appendAssumeCapacity(.{
3405 .tag = .extern_func,
3406 .data = try ip.addExtra(gpa, @as(Tag.ExternFunc, extern_func)),
3407 }),
3408
3409 .func => |func| ip.items.appendAssumeCapacity(.{
3410 .tag = .func,
3411 .data = try ip.addExtra(gpa, @as(Tag.Func, func)),
3412 }),
3413
3414 .ptr => |ptr| {
3415 const ptr_type = ip.indexToKey(ptr.ty).ptr_type;
3416 switch (ptr.len) {
3417 .none => {
3418 assert(ptr_type.flags.size != .Slice);
3419 switch (ptr.addr) {
3420 .decl => |decl| ip.items.appendAssumeCapacity(.{
3421 .tag = .ptr_decl,
3422 .data = try ip.addExtra(gpa, PtrDecl{
3423 .ty = ptr.ty,
3424 .decl = decl,
3425 }),
3426 }),
3427 .mut_decl => |mut_decl| ip.items.appendAssumeCapacity(.{
3428 .tag = .ptr_mut_decl,
3429 .data = try ip.addExtra(gpa, PtrMutDecl{
3430 .ty = ptr.ty,
3431 .decl = mut_decl.decl,
3432 .runtime_index = mut_decl.runtime_index,
3433 }),
3434 }),
3435 .comptime_field => |field_val| {
3436 assert(field_val != .none);
3437 ip.items.appendAssumeCapacity(.{
3438 .tag = .ptr_comptime_field,
3439 .data = try ip.addExtra(gpa, PtrComptimeField{
3440 .ty = ptr.ty,
3441 .field_val = field_val,
3442 }),
3443 });
3444 },
3445 .int, .eu_payload, .opt_payload => |base| {
3446 switch (ptr.addr) {
3447 .int => assert(ip.typeOf(base) == .usize_type),
3448 .eu_payload => assert(ip.indexToKey(
3449 ip.indexToKey(ip.typeOf(base)).ptr_type.child,
3450 ) == .error_union_type),
3451 .opt_payload => assert(ip.indexToKey(
3452 ip.indexToKey(ip.typeOf(base)).ptr_type.child,
3453 ) == .opt_type),
3454 else => unreachable,
3455 }
3456 ip.items.appendAssumeCapacity(.{
3457 .tag = switch (ptr.addr) {
3458 .int => .ptr_int,
3459 .eu_payload => .ptr_eu_payload,
3460 .opt_payload => .ptr_opt_payload,
3461 else => unreachable,
3462 },
3463 .data = try ip.addExtra(gpa, PtrBase{
3464 .ty = ptr.ty,
3465 .base = base,
3466 }),
3467 });
3468 },
3469 .elem, .field => |base_index| {
3470 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type;
3471 switch (ptr.addr) {
3472 .elem => assert(base_ptr_type.flags.size == .Many),
3473 .field => {
3474 assert(base_ptr_type.flags.size == .One);
3475 switch (ip.indexToKey(base_ptr_type.child)) {
3476 .anon_struct_type => |anon_struct_type| {
3477 assert(ptr.addr == .field);
3478 assert(base_index.index < anon_struct_type.types.len);
3479 },
3480 .struct_type => |struct_type| {
3481 assert(ptr.addr == .field);
3482 assert(base_index.index < ip.structPtrUnwrapConst(struct_type.index).?.fields.count());
3483 },
3484 .union_type => |union_type| {
3485 assert(ptr.addr == .field);
3486 assert(base_index.index < ip.unionPtrConst(union_type.index).fields.count());
3487 },
3488 .ptr_type => |slice_type| {
3489 assert(ptr.addr == .field);
3490 assert(slice_type.flags.size == .Slice);
3491 assert(base_index.index < 2);
3492 },
3493 else => unreachable,
3494 }
3495 },
3496 else => unreachable,
3497 }
3498 _ = ip.map.pop();
3499 const index_index = try ip.get(gpa, .{ .int = .{
3500 .ty = .usize_type,
3501 .storage = .{ .u64 = base_index.index },
3502 } });
3503 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3504 try ip.items.ensureUnusedCapacity(gpa, 1);
3505 ip.items.appendAssumeCapacity(.{
3506 .tag = switch (ptr.addr) {
3507 .elem => .ptr_elem,
3508 .field => .ptr_field,
3509 else => unreachable,
3510 },
3511 .data = try ip.addExtra(gpa, PtrBaseIndex{
3512 .ty = ptr.ty,
3513 .base = base_index.base,
3514 .index = index_index,
3515 }),
3516 });
3517 },
3518 }
3519 },
3520 else => {
3521 // TODO: change Key.Ptr for slices to reference the manyptr value
3522 // rather than having an addr field directly. Then we can avoid
3523 // these problematic calls to pop(), get(), and getOrPutAdapted().
3524 assert(ptr_type.flags.size == .Slice);
3525 _ = ip.map.pop();
3526 var new_key = key;
3527 new_key.ptr.ty = ip.slicePtrType(ptr.ty);
3528 new_key.ptr.len = .none;
3529 assert(ip.indexToKey(new_key.ptr.ty).ptr_type.flags.size == .Many);
3530 const ptr_index = try ip.get(gpa, new_key);
3531 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3532 try ip.items.ensureUnusedCapacity(gpa, 1);
3533 ip.items.appendAssumeCapacity(.{
3534 .tag = .ptr_slice,
3535 .data = try ip.addExtra(gpa, PtrSlice{
3536 .ty = ptr.ty,
3537 .ptr = ptr_index,
3538 .len = ptr.len,
3539 }),
3540 });
3541 },
3542 }
3543 assert(ptr.ty == ip.indexToKey(@intToEnum(Index, ip.items.len - 1)).ptr.ty);
3544 },
3545
3546 .opt => |opt| {
3547 assert(ip.isOptionalType(opt.ty));
3548 assert(opt.val == .none or ip.indexToKey(opt.ty).opt_type == ip.typeOf(opt.val));
3549 ip.items.appendAssumeCapacity(if (opt.val == .none) .{
3550 .tag = .opt_null,
3551 .data = @enumToInt(opt.ty),
3552 } else .{
3553 .tag = .opt_payload,
3554 .data = try ip.addExtra(gpa, Tag.TypeValue{
3555 .ty = opt.ty,
3556 .val = opt.val,
3557 }),
3558 });
3559 },
3560
3561 .int => |int| b: {
3562 assert(ip.isIntegerType(int.ty));
3563 switch (int.storage) {
3564 .u64, .i64, .big_int => {},
3565 .lazy_align, .lazy_size => |lazy_ty| {
3566 ip.items.appendAssumeCapacity(.{
3567 .tag = switch (int.storage) {
3568 else => unreachable,
3569 .lazy_align => .int_lazy_align,
3570 .lazy_size => .int_lazy_size,
3571 },
3572 .data = try ip.addExtra(gpa, IntLazy{
3573 .ty = int.ty,
3574 .lazy_ty = lazy_ty,
3575 }),
3576 });
3577 return @intToEnum(Index, ip.items.len - 1);
3578 },
3579 }
3580 switch (int.ty) {
3581 .u8_type => switch (int.storage) {
3582 .big_int => |big_int| {
3583 ip.items.appendAssumeCapacity(.{
3584 .tag = .int_u8,
3585 .data = big_int.to(u8) catch unreachable,
3586 });
3587 break :b;
3588 },
3589 inline .u64, .i64 => |x| {
3590 ip.items.appendAssumeCapacity(.{
3591 .tag = .int_u8,
3592 .data = @intCast(u8, x),
3593 });
3594 break :b;
3595 },
3596 .lazy_align, .lazy_size => unreachable,
3597 },
3598 .u16_type => switch (int.storage) {
3599 .big_int => |big_int| {
3600 ip.items.appendAssumeCapacity(.{
3601 .tag = .int_u16,
3602 .data = big_int.to(u16) catch unreachable,
3603 });
3604 break :b;
3605 },
3606 inline .u64, .i64 => |x| {
3607 ip.items.appendAssumeCapacity(.{
3608 .tag = .int_u16,
3609 .data = @intCast(u16, x),
3610 });
3611 break :b;
3612 },
3613 .lazy_align, .lazy_size => unreachable,
3614 },
3615 .u32_type => switch (int.storage) {
3616 .big_int => |big_int| {
3617 ip.items.appendAssumeCapacity(.{
3618 .tag = .int_u32,
3619 .data = big_int.to(u32) catch unreachable,
3620 });
3621 break :b;
3622 },
3623 inline .u64, .i64 => |x| {
3624 ip.items.appendAssumeCapacity(.{
3625 .tag = .int_u32,
3626 .data = @intCast(u32, x),
3627 });
3628 break :b;
3629 },
3630 .lazy_align, .lazy_size => unreachable,
3631 },
3632 .i32_type => switch (int.storage) {
3633 .big_int => |big_int| {
3634 const casted = big_int.to(i32) catch unreachable;
3635 ip.items.appendAssumeCapacity(.{
3636 .tag = .int_i32,
3637 .data = @bitCast(u32, casted),
3638 });
3639 break :b;
3640 },
3641 inline .u64, .i64 => |x| {
3642 ip.items.appendAssumeCapacity(.{
3643 .tag = .int_i32,
3644 .data = @bitCast(u32, @intCast(i32, x)),
3645 });
3646 break :b;
3647 },
3648 .lazy_align, .lazy_size => unreachable,
3649 },
3650 .usize_type => switch (int.storage) {
3651 .big_int => |big_int| {
3652 if (big_int.to(u32)) |casted| {
3653 ip.items.appendAssumeCapacity(.{
3654 .tag = .int_usize,
3655 .data = casted,
3656 });
3657 break :b;
3658 } else |_| {}
3659 },
3660 inline .u64, .i64 => |x| {
3661 if (std.math.cast(u32, x)) |casted| {
3662 ip.items.appendAssumeCapacity(.{
3663 .tag = .int_usize,
3664 .data = casted,
3665 });
3666 break :b;
3667 }
3668 },
3669 .lazy_align, .lazy_size => unreachable,
3670 },
3671 .comptime_int_type => switch (int.storage) {
3672 .big_int => |big_int| {
3673 if (big_int.to(u32)) |casted| {
3674 ip.items.appendAssumeCapacity(.{
3675 .tag = .int_comptime_int_u32,
3676 .data = casted,
3677 });
3678 break :b;
3679 } else |_| {}
3680 if (big_int.to(i32)) |casted| {
3681 ip.items.appendAssumeCapacity(.{
3682 .tag = .int_comptime_int_i32,
3683 .data = @bitCast(u32, casted),
3684 });
3685 break :b;
3686 } else |_| {}
3687 },
3688 inline .u64, .i64 => |x| {
3689 if (std.math.cast(u32, x)) |casted| {
3690 ip.items.appendAssumeCapacity(.{
3691 .tag = .int_comptime_int_u32,
3692 .data = casted,
3693 });
3694 break :b;
3695 }
3696 if (std.math.cast(i32, x)) |casted| {
3697 ip.items.appendAssumeCapacity(.{
3698 .tag = .int_comptime_int_i32,
3699 .data = @bitCast(u32, casted),
3700 });
3701 break :b;
3702 }
3703 },
3704 .lazy_align, .lazy_size => unreachable,
3705 },
3706 else => {},
3707 }
3708 switch (int.storage) {
3709 .big_int => |big_int| {
3710 if (big_int.to(u32)) |casted| {
3711 ip.items.appendAssumeCapacity(.{
3712 .tag = .int_small,
3713 .data = try ip.addExtra(gpa, IntSmall{
3714 .ty = int.ty,
3715 .value = casted,
3716 }),
3717 });
3718 return @intToEnum(Index, ip.items.len - 1);
3719 } else |_| {}
3720
3721 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
3722 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
3723 },
3724 inline .u64, .i64 => |x| {
3725 if (std.math.cast(u32, x)) |casted| {
3726 ip.items.appendAssumeCapacity(.{
3727 .tag = .int_small,
3728 .data = try ip.addExtra(gpa, IntSmall{
3729 .ty = int.ty,
3730 .value = casted,
3731 }),
3732 });
3733 return @intToEnum(Index, ip.items.len - 1);
3734 }
3735
3736 var buf: [2]Limb = undefined;
3737 const big_int = BigIntMutable.init(&buf, x).toConst();
3738 const tag: Tag = if (big_int.positive) .int_positive else .int_negative;
3739 try addInt(ip, gpa, int.ty, tag, big_int.limbs);
3740 },
3741 .lazy_align, .lazy_size => unreachable,
3742 }
3743 },
3744
3745 .err => |err| {
3746 assert(ip.isErrorSetType(err.ty));
3747 ip.items.appendAssumeCapacity(.{
3748 .tag = .error_set_error,
3749 .data = try ip.addExtra(gpa, err),
3750 });
3751 },
3752
3753 .error_union => |error_union| {
3754 assert(ip.isErrorUnionType(error_union.ty));
3755 ip.items.appendAssumeCapacity(switch (error_union.val) {
3756 .err_name => |err_name| .{
3757 .tag = .error_union_error,
3758 .data = try ip.addExtra(gpa, Key.Error{
3759 .ty = error_union.ty,
3760 .name = err_name,
3761 }),
3762 },
3763 .payload => |payload| .{
3764 .tag = .error_union_payload,
3765 .data = try ip.addExtra(gpa, Tag.TypeValue{
3766 .ty = error_union.ty,
3767 .val = payload,
3768 }),
3769 },
3770 });
3771 },
3772
3773 .enum_literal => |enum_literal| ip.items.appendAssumeCapacity(.{
3774 .tag = .enum_literal,
3775 .data = @enumToInt(enum_literal),
3776 }),
3777
3778 .enum_tag => |enum_tag| {
3779 assert(ip.isEnumType(enum_tag.ty));
3780 switch (ip.indexToKey(enum_tag.ty)) {
3781 .simple_type => assert(ip.isIntegerType(ip.typeOf(enum_tag.int))),
3782 .enum_type => |enum_type| assert(ip.typeOf(enum_tag.int) == enum_type.tag_ty),
3783 else => unreachable,
3784 }
3785 ip.items.appendAssumeCapacity(.{
3786 .tag = .enum_tag,
3787 .data = try ip.addExtra(gpa, enum_tag),
3788 });
3789 },
3790
3791 .empty_enum_value => |enum_or_union_ty| ip.items.appendAssumeCapacity(.{
3792 .tag = .only_possible_value,
3793 .data = @enumToInt(enum_or_union_ty),
3794 }),
3795
3796 .float => |float| {
3797 switch (float.ty) {
3798 .f16_type => ip.items.appendAssumeCapacity(.{
3799 .tag = .float_f16,
3800 .data = @bitCast(u16, float.storage.f16),
3801 }),
3802 .f32_type => ip.items.appendAssumeCapacity(.{
3803 .tag = .float_f32,
3804 .data = @bitCast(u32, float.storage.f32),
3805 }),
3806 .f64_type => ip.items.appendAssumeCapacity(.{
3807 .tag = .float_f64,
3808 .data = try ip.addExtra(gpa, Float64.pack(float.storage.f64)),
3809 }),
3810 .f80_type => ip.items.appendAssumeCapacity(.{
3811 .tag = .float_f80,
3812 .data = try ip.addExtra(gpa, Float80.pack(float.storage.f80)),
3813 }),
3814 .f128_type => ip.items.appendAssumeCapacity(.{
3815 .tag = .float_f128,
3816 .data = try ip.addExtra(gpa, Float128.pack(float.storage.f128)),
3817 }),
3818 .c_longdouble_type => switch (float.storage) {
3819 .f80 => |x| ip.items.appendAssumeCapacity(.{
3820 .tag = .float_c_longdouble_f80,
3821 .data = try ip.addExtra(gpa, Float80.pack(x)),
3822 }),
3823 inline .f16, .f32, .f64, .f128 => |x| ip.items.appendAssumeCapacity(.{
3824 .tag = .float_c_longdouble_f128,
3825 .data = try ip.addExtra(gpa, Float128.pack(x)),
3826 }),
3827 },
3828 .comptime_float_type => ip.items.appendAssumeCapacity(.{
3829 .tag = .float_comptime_float,
3830 .data = try ip.addExtra(gpa, Float128.pack(float.storage.f128)),
3831 }),
3832 else => unreachable,
3833 }
3834 },
3835
3836 .aggregate => |aggregate| {
3837 const ty_key = ip.indexToKey(aggregate.ty);
3838 const len = ip.aggregateTypeLen(aggregate.ty);
3839 const child = switch (ty_key) {
3840 .array_type => |array_type| array_type.child,
3841 .vector_type => |vector_type| vector_type.child,
3842 .anon_struct_type, .struct_type => .none,
3843 else => unreachable,
3844 };
3845 const sentinel = switch (ty_key) {
3846 .array_type => |array_type| array_type.sentinel,
3847 .vector_type, .anon_struct_type, .struct_type => .none,
3848 else => unreachable,
3849 };
3850 const len_including_sentinel = len + @boolToInt(sentinel != .none);
3851 switch (aggregate.storage) {
3852 .bytes => |bytes| {
3853 assert(child == .u8_type);
3854 if (bytes.len != len) {
3855 assert(bytes.len == len_including_sentinel);
3856 assert(bytes[@intCast(usize, len)] == ip.indexToKey(sentinel).int.storage.u64);
3857 }
3858 },
3859 .elems => |elems| {
3860 if (elems.len != len) {
3861 assert(elems.len == len_including_sentinel);
3862 assert(elems[@intCast(usize, len)] == sentinel);
3863 }
3864 },
3865 .repeated_elem => |elem| {
3866 assert(sentinel == .none or elem == sentinel);
3867 },
3868 }
3869 switch (ty_key) {
3870 .array_type, .vector_type => {
3871 for (aggregate.storage.values()) |elem| {
3872 assert(ip.typeOf(elem) == child);
3873 }
3874 },
3875 .struct_type => |struct_type| {
3876 for (
3877 aggregate.storage.values(),
3878 ip.structPtrUnwrapConst(struct_type.index).?.fields.values(),
3879 ) |elem, field| {
3880 assert(ip.typeOf(elem) == field.ty.toIntern());
3881 }
3882 },
3883 .anon_struct_type => |anon_struct_type| {
3884 for (aggregate.storage.values(), anon_struct_type.types) |elem, ty| {
3885 assert(ip.typeOf(elem) == ty);
3886 }
3887 },
3888 else => unreachable,
3889 }
3890
3891 if (len == 0) {
3892 ip.items.appendAssumeCapacity(.{
3893 .tag = .only_possible_value,
3894 .data = @enumToInt(aggregate.ty),
3895 });
3896 return @intToEnum(Index, ip.items.len - 1);
3897 }
3898
3899 switch (ty_key) {
3900 .anon_struct_type => |anon_struct_type| opv: {
3901 switch (aggregate.storage) {
3902 .bytes => |bytes| for (anon_struct_type.values, bytes) |value, byte| {
3903 if (value != ip.getIfExists(.{ .int = .{
3904 .ty = .u8_type,
3905 .storage = .{ .u64 = byte },
3906 } })) break :opv;
3907 },
3908 .elems => |elems| if (!std.mem.eql(
3909 Index,
3910 anon_struct_type.values,
3911 elems,
3912 )) break :opv,
3913 .repeated_elem => |elem| for (anon_struct_type.values) |value| {
3914 if (value != elem) break :opv;
3915 },
3916 }
3917 // This encoding works thanks to the fact that, as we just verified,
3918 // the type itself contains a slice of values that can be provided
3919 // in the aggregate fields.
3920 ip.items.appendAssumeCapacity(.{
3921 .tag = .only_possible_value,
3922 .data = @enumToInt(aggregate.ty),
3923 });
3924 return @intToEnum(Index, ip.items.len - 1);
3925 },
3926 else => {},
3927 }
3928
3929 repeated: {
3930 switch (aggregate.storage) {
3931 .bytes => |bytes| for (bytes[1..@intCast(usize, len)]) |byte|
3932 if (byte != bytes[0]) break :repeated,
3933 .elems => |elems| for (elems[1..@intCast(usize, len)]) |elem|
3934 if (elem != elems[0]) break :repeated,
3935 .repeated_elem => {},
3936 }
3937 const elem = switch (aggregate.storage) {
3938 .bytes => |bytes| elem: {
3939 _ = ip.map.pop();
3940 const elem = try ip.get(gpa, .{ .int = .{
3941 .ty = .u8_type,
3942 .storage = .{ .u64 = bytes[0] },
3943 } });
3944 assert(!(try ip.map.getOrPutAdapted(gpa, key, adapter)).found_existing);
3945 try ip.items.ensureUnusedCapacity(gpa, 1);
3946 break :elem elem;
3947 },
3948 .elems => |elems| elems[0],
3949 .repeated_elem => |elem| elem,
3950 };
3951
3952 try ip.extra.ensureUnusedCapacity(
3953 gpa,
3954 @typeInfo(Repeated).Struct.fields.len,
3955 );
3956 ip.items.appendAssumeCapacity(.{
3957 .tag = .repeated,
3958 .data = ip.addExtraAssumeCapacity(Repeated{
3959 .ty = aggregate.ty,
3960 .elem_val = elem,
3961 }),
3962 });
3963 return @intToEnum(Index, ip.items.len - 1);
3964 }
3965
3966 if (child == .u8_type) bytes: {
3967 const string_bytes_index = ip.string_bytes.items.len;
3968 try ip.string_bytes.ensureUnusedCapacity(gpa, @intCast(usize, len_including_sentinel + 1));
3969 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(Bytes).Struct.fields.len);
3970 switch (aggregate.storage) {
3971 .bytes => |bytes| ip.string_bytes.appendSliceAssumeCapacity(bytes),
3972 .elems => |elems| for (elems) |elem| switch (ip.indexToKey(elem)) {
3973 .undef => {
3974 ip.string_bytes.shrinkRetainingCapacity(string_bytes_index);
3975 break :bytes;
3976 },
3977 .int => |int| ip.string_bytes.appendAssumeCapacity(
3978 @intCast(u8, int.storage.u64),
3979 ),
3980 else => unreachable,
3981 },
3982 .repeated_elem => |elem| switch (ip.indexToKey(elem)) {
3983 .undef => break :bytes,
3984 .int => |int| @memset(
3985 ip.string_bytes.addManyAsSliceAssumeCapacity(@intCast(usize, len)),
3986 @intCast(u8, int.storage.u64),
3987 ),
3988 else => unreachable,
3989 },
3990 }
3991 const has_internal_null =
3992 std.mem.indexOfScalar(u8, ip.string_bytes.items[string_bytes_index..], 0) != null;
3993 if (sentinel != .none) ip.string_bytes.appendAssumeCapacity(
3994 @intCast(u8, ip.indexToKey(sentinel).int.storage.u64),
3995 );
3996 const string = if (has_internal_null)
3997 @intToEnum(String, string_bytes_index)
3998 else
3999 (try ip.getOrPutTrailingString(gpa, @intCast(usize, len_including_sentinel))).toString();
4000 ip.items.appendAssumeCapacity(.{
4001 .tag = .bytes,
4002 .data = ip.addExtraAssumeCapacity(Bytes{
4003 .ty = aggregate.ty,
4004 .bytes = string,
4005 }),
4006 });
4007 return @intToEnum(Index, ip.items.len - 1);
4008 }
4009
4010 try ip.extra.ensureUnusedCapacity(
4011 gpa,
4012 @typeInfo(Tag.Aggregate).Struct.fields.len + @intCast(usize, len_including_sentinel),
4013 );
4014 ip.items.appendAssumeCapacity(.{
4015 .tag = .aggregate,
4016 .data = ip.addExtraAssumeCapacity(Tag.Aggregate{
4017 .ty = aggregate.ty,
4018 }),
4019 });
4020 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems));
4021 if (sentinel != .none) ip.extra.appendAssumeCapacity(@enumToInt(sentinel));
4022 },
4023
4024 .un => |un| {
4025 assert(un.ty != .none);
4026 assert(un.tag != .none);
4027 assert(un.val != .none);
4028 ip.items.appendAssumeCapacity(.{
4029 .tag = .union_value,
4030 .data = try ip.addExtra(gpa, un),
4031 });
4032 },
4033
4034 .memoized_call => |memoized_call| {
4035 for (memoized_call.arg_values) |arg| assert(arg != .none);
4036 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(MemoizedCall).Struct.fields.len +
4037 memoized_call.arg_values.len);
4038 ip.items.appendAssumeCapacity(.{
4039 .tag = .memoized_call,
4040 .data = ip.addExtraAssumeCapacity(MemoizedCall{
4041 .func = memoized_call.func,
4042 .args_len = @intCast(u32, memoized_call.arg_values.len),
4043 .result = memoized_call.result,
4044 }),
4045 });
4046 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, memoized_call.arg_values));
4047 },
4048 }
4049 return @intToEnum(Index, ip.items.len - 1);
4050}
4051
4052/// Provides API for completing an enum type after calling `getIncompleteEnum`.
4053pub const IncompleteEnumType = struct {
4054 index: Index,
4055 tag_ty_index: u32,
4056 names_map: MapIndex,
4057 names_start: u32,
4058 values_map: OptionalMapIndex,
4059 values_start: u32,
4060
4061 pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void {
4062 assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty));
4063 ip.extra.items[self.tag_ty_index] = @enumToInt(tag_ty);
4064 }
4065
4066 /// Returns the already-existing field with the same name, if any.
4067 pub fn addFieldName(
4068 self: @This(),
4069 ip: *InternPool,
4070 gpa: Allocator,
4071 name: NullTerminatedString,
4072 ) Allocator.Error!?u32 {
4073 const map = &ip.maps.items[@enumToInt(self.names_map)];
4074 const field_index = map.count();
4075 const strings = ip.extra.items[self.names_start..][0..field_index];
4076 const adapter: NullTerminatedString.Adapter = .{
4077 .strings = @ptrCast([]const NullTerminatedString, strings),
4078 };
4079 const gop = try map.getOrPutAdapted(gpa, name, adapter);
4080 if (gop.found_existing) return @intCast(u32, gop.index);
4081 ip.extra.items[self.names_start + field_index] = @enumToInt(name);
4082 return null;
4083 }
4084
4085 /// Returns the already-existing field with the same value, if any.
4086 /// Make sure the type of the value has the integer tag type of the enum.
4087 pub fn addFieldValue(
4088 self: @This(),
4089 ip: *InternPool,
4090 gpa: Allocator,
4091 value: Index,
4092 ) Allocator.Error!?u32 {
4093 assert(ip.typeOf(value) == @intToEnum(Index, ip.extra.items[self.tag_ty_index]));
4094 const map = &ip.maps.items[@enumToInt(self.values_map.unwrap().?)];
4095 const field_index = map.count();
4096 const indexes = ip.extra.items[self.values_start..][0..field_index];
4097 const adapter: Index.Adapter = .{
4098 .indexes = @ptrCast([]const Index, indexes),
4099 };
4100 const gop = try map.getOrPutAdapted(gpa, value, adapter);
4101 if (gop.found_existing) return @intCast(u32, gop.index);
4102 ip.extra.items[self.values_start + field_index] = @enumToInt(value);
4103 return null;
4104 }
4105};
4106
4107/// This is used to create an enum type in the `InternPool`, with the ability
4108/// to update the tag type, field names, and field values later.
4109pub fn getIncompleteEnum(
4110 ip: *InternPool,
4111 gpa: Allocator,
4112 enum_type: Key.IncompleteEnumType,
4113) Allocator.Error!IncompleteEnumType {
4114 switch (enum_type.tag_mode) {
4115 .auto => return getIncompleteEnumAuto(ip, gpa, enum_type),
4116 .explicit => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_explicit),
4117 .nonexhaustive => return getIncompleteEnumExplicit(ip, gpa, enum_type, .type_enum_nonexhaustive),
4118 }
4119}
4120
4121fn getIncompleteEnumAuto(
4122 ip: *InternPool,
4123 gpa: Allocator,
4124 enum_type: Key.IncompleteEnumType,
4125) Allocator.Error!IncompleteEnumType {
4126 const int_tag_type = if (enum_type.tag_ty != .none)
4127 enum_type.tag_ty
4128 else
4129 try ip.get(gpa, .{ .int_type = .{
4130 .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len),
4131 .signedness = .unsigned,
4132 } });
4133
4134 // We must keep the map in sync with `items`. The hash and equality functions
4135 // for enum types only look at the decl field, which is present even in
4136 // an `IncompleteEnumType`.
4137 const adapter: KeyAdapter = .{ .intern_pool = ip };
4138 const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter);
4139 assert(!gop.found_existing);
4140
4141 const names_map = try ip.addMap(gpa);
4142
4143 const extra_fields_len: u32 = @typeInfo(EnumAuto).Struct.fields.len;
4144 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + enum_type.fields_len);
4145 try ip.items.ensureUnusedCapacity(gpa, 1);
4146
4147 const extra_index = ip.addExtraAssumeCapacity(EnumAuto{
4148 .decl = enum_type.decl,
4149 .namespace = enum_type.namespace,
4150 .int_tag_type = int_tag_type,
4151 .names_map = names_map,
4152 .fields_len = enum_type.fields_len,
4153 });
4154
4155 ip.items.appendAssumeCapacity(.{
4156 .tag = .type_enum_auto,
4157 .data = extra_index,
4158 });
4159 ip.extra.appendNTimesAssumeCapacity(@enumToInt(Index.none), enum_type.fields_len);
4160 return .{
4161 .index = @intToEnum(Index, ip.items.len - 1),
4162 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
4163 .names_map = names_map,
4164 .names_start = extra_index + extra_fields_len,
4165 .values_map = .none,
4166 .values_start = undefined,
4167 };
4168}
4169
4170fn getIncompleteEnumExplicit(
4171 ip: *InternPool,
4172 gpa: Allocator,
4173 enum_type: Key.IncompleteEnumType,
4174 tag: Tag,
4175) Allocator.Error!IncompleteEnumType {
4176 // We must keep the map in sync with `items`. The hash and equality functions
4177 // for enum types only look at the decl field, which is present even in
4178 // an `IncompleteEnumType`.
4179 const adapter: KeyAdapter = .{ .intern_pool = ip };
4180 const gop = try ip.map.getOrPutAdapted(gpa, enum_type.toKey(), adapter);
4181 assert(!gop.found_existing);
4182
4183 const names_map = try ip.addMap(gpa);
4184 const values_map: OptionalMapIndex = if (!enum_type.has_values) .none else m: {
4185 const values_map = try ip.addMap(gpa);
4186 break :m values_map.toOptional();
4187 };
4188
4189 const reserved_len = enum_type.fields_len +
4190 if (enum_type.has_values) enum_type.fields_len else 0;
4191
4192 const extra_fields_len: u32 = @typeInfo(EnumExplicit).Struct.fields.len;
4193 try ip.extra.ensureUnusedCapacity(gpa, extra_fields_len + reserved_len);
4194 try ip.items.ensureUnusedCapacity(gpa, 1);
4195
4196 const extra_index = ip.addExtraAssumeCapacity(EnumExplicit{
4197 .decl = enum_type.decl,
4198 .namespace = enum_type.namespace,
4199 .int_tag_type = enum_type.tag_ty,
4200 .fields_len = enum_type.fields_len,
4201 .names_map = names_map,
4202 .values_map = values_map,
4203 });
4204
4205 ip.items.appendAssumeCapacity(.{
4206 .tag = tag,
4207 .data = extra_index,
4208 });
4209 // This is both fields and values (if present).
4210 ip.extra.appendNTimesAssumeCapacity(@enumToInt(Index.none), reserved_len);
4211 return .{
4212 .index = @intToEnum(Index, ip.items.len - 1),
4213 .tag_ty_index = extra_index + std.meta.fieldIndex(EnumExplicit, "int_tag_type").?,
4214 .names_map = names_map,
4215 .names_start = extra_index + extra_fields_len,
4216 .values_map = values_map,
4217 .values_start = extra_index + extra_fields_len + enum_type.fields_len,
4218 };
4219}
4220
4221pub fn finishGetEnum(
4222 ip: *InternPool,
4223 gpa: Allocator,
4224 enum_type: Key.EnumType,
4225 tag: Tag,
4226) Allocator.Error!Index {
4227 const names_map = try ip.addMap(gpa);
4228 try addStringsToMap(ip, gpa, names_map, enum_type.names);
4229
4230 const values_map: OptionalMapIndex = if (enum_type.values.len == 0) .none else m: {
4231 const values_map = try ip.addMap(gpa);
4232 try addIndexesToMap(ip, gpa, values_map, enum_type.values);
4233 break :m values_map.toOptional();
4234 };
4235 const fields_len = @intCast(u32, enum_type.names.len);
4236 try ip.extra.ensureUnusedCapacity(gpa, @typeInfo(EnumExplicit).Struct.fields.len +
4237 fields_len);
4238 ip.items.appendAssumeCapacity(.{
4239 .tag = tag,
4240 .data = ip.addExtraAssumeCapacity(EnumExplicit{
4241 .decl = enum_type.decl,
4242 .namespace = enum_type.namespace,
4243 .int_tag_type = enum_type.tag_ty,
4244 .fields_len = fields_len,
4245 .names_map = names_map,
4246 .values_map = values_map,
4247 }),
4248 });
4249 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, enum_type.names));
4250 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, enum_type.values));
4251 return @intToEnum(Index, ip.items.len - 1);
4252}
4253
4254pub fn getIfExists(ip: *const InternPool, key: Key) ?Index {
4255 const adapter: KeyAdapter = .{ .intern_pool = ip };
4256 const index = ip.map.getIndexAdapted(key, adapter) orelse return null;
4257 return @intToEnum(Index, index);
4258}
4259
4260pub fn getAssumeExists(ip: *const InternPool, key: Key) Index {
4261 return ip.getIfExists(key).?;
4262}
4263
4264fn addStringsToMap(
4265 ip: *InternPool,
4266 gpa: Allocator,
4267 map_index: MapIndex,
4268 strings: []const NullTerminatedString,
4269) Allocator.Error!void {
4270 const map = &ip.maps.items[@enumToInt(map_index)];
4271 const adapter: NullTerminatedString.Adapter = .{ .strings = strings };
4272 for (strings) |string| {
4273 const gop = try map.getOrPutAdapted(gpa, string, adapter);
4274 assert(!gop.found_existing);
4275 }
4276}
4277
4278fn addIndexesToMap(
4279 ip: *InternPool,
4280 gpa: Allocator,
4281 map_index: MapIndex,
4282 indexes: []const Index,
4283) Allocator.Error!void {
4284 const map = &ip.maps.items[@enumToInt(map_index)];
4285 const adapter: Index.Adapter = .{ .indexes = indexes };
4286 for (indexes) |index| {
4287 const gop = try map.getOrPutAdapted(gpa, index, adapter);
4288 assert(!gop.found_existing);
4289 }
4290}
4291
4292fn addMap(ip: *InternPool, gpa: Allocator) Allocator.Error!MapIndex {
4293 const ptr = try ip.maps.addOne(gpa);
4294 ptr.* = .{};
4295 return @intToEnum(MapIndex, ip.maps.items.len - 1);
4296}
4297
4298/// This operation only happens under compile error conditions.
4299/// Leak the index until the next garbage collection.
4300/// TODO: this is a bit problematic to implement, can we get away without it?
4301pub const remove = @compileError("InternPool.remove is not currently a supported operation; put a TODO there instead");
4302
4303fn addInt(ip: *InternPool, gpa: Allocator, ty: Index, tag: Tag, limbs: []const Limb) !void {
4304 const limbs_len = @intCast(u32, limbs.len);
4305 try ip.reserveLimbs(gpa, @typeInfo(Int).Struct.fields.len + limbs_len);
4306 ip.items.appendAssumeCapacity(.{
4307 .tag = tag,
4308 .data = ip.addLimbsExtraAssumeCapacity(Int{
4309 .ty = ty,
4310 .limbs_len = limbs_len,
4311 }),
4312 });
4313 ip.addLimbsAssumeCapacity(limbs);
4314}
4315
4316fn addExtra(ip: *InternPool, gpa: Allocator, extra: anytype) Allocator.Error!u32 {
4317 const fields = @typeInfo(@TypeOf(extra)).Struct.fields;
4318 try ip.extra.ensureUnusedCapacity(gpa, fields.len);
4319 return ip.addExtraAssumeCapacity(extra);
4320}
4321
4322fn addExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
4323 const result = @intCast(u32, ip.extra.items.len);
4324 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
4325 ip.extra.appendAssumeCapacity(switch (field.type) {
4326 u32 => @field(extra, field.name),
4327 Index => @enumToInt(@field(extra, field.name)),
4328 Module.Decl.Index => @enumToInt(@field(extra, field.name)),
4329 Module.Namespace.Index => @enumToInt(@field(extra, field.name)),
4330 Module.Namespace.OptionalIndex => @enumToInt(@field(extra, field.name)),
4331 Module.Fn.Index => @enumToInt(@field(extra, field.name)),
4332 MapIndex => @enumToInt(@field(extra, field.name)),
4333 OptionalMapIndex => @enumToInt(@field(extra, field.name)),
4334 RuntimeIndex => @enumToInt(@field(extra, field.name)),
4335 String => @enumToInt(@field(extra, field.name)),
4336 NullTerminatedString => @enumToInt(@field(extra, field.name)),
4337 OptionalNullTerminatedString => @enumToInt(@field(extra, field.name)),
4338 i32 => @bitCast(u32, @field(extra, field.name)),
4339 Tag.TypePointer.Flags => @bitCast(u32, @field(extra, field.name)),
4340 TypeFunction.Flags => @bitCast(u32, @field(extra, field.name)),
4341 Tag.TypePointer.PackedOffset => @bitCast(u32, @field(extra, field.name)),
4342 Tag.TypePointer.VectorIndex => @enumToInt(@field(extra, field.name)),
4343 Tag.Variable.Flags => @bitCast(u32, @field(extra, field.name)),
4344 else => @compileError("bad field type: " ++ @typeName(field.type)),
4345 });
4346 }
4347 return result;
4348}
4349
4350fn reserveLimbs(ip: *InternPool, gpa: Allocator, n: usize) !void {
4351 switch (@sizeOf(Limb)) {
4352 @sizeOf(u32) => try ip.extra.ensureUnusedCapacity(gpa, n),
4353 @sizeOf(u64) => try ip.limbs.ensureUnusedCapacity(gpa, n),
4354 else => @compileError("unsupported host"),
4355 }
4356}
4357
4358fn addLimbsExtraAssumeCapacity(ip: *InternPool, extra: anytype) u32 {
4359 switch (@sizeOf(Limb)) {
4360 @sizeOf(u32) => return addExtraAssumeCapacity(ip, extra),
4361 @sizeOf(u64) => {},
4362 else => @compileError("unsupported host"),
4363 }
4364 const result = @intCast(u32, ip.limbs.items.len);
4365 inline for (@typeInfo(@TypeOf(extra)).Struct.fields, 0..) |field, i| {
4366 const new: u32 = switch (field.type) {
4367 u32 => @field(extra, field.name),
4368 Index => @enumToInt(@field(extra, field.name)),
4369 else => @compileError("bad field type: " ++ @typeName(field.type)),
4370 };
4371 if (i % 2 == 0) {
4372 ip.limbs.appendAssumeCapacity(new);
4373 } else {
4374 ip.limbs.items[ip.limbs.items.len - 1] |= @as(u64, new) << 32;
4375 }
4376 }
4377 return result;
4378}
4379
4380fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {
4381 switch (@sizeOf(Limb)) {
4382 @sizeOf(u32) => ip.extra.appendSliceAssumeCapacity(limbs),
4383 @sizeOf(u64) => ip.limbs.appendSliceAssumeCapacity(limbs),
4384 else => @compileError("unsupported host"),
4385 }
4386}
4387
4388fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct { data: T, end: usize } {
4389 var result: T = undefined;
4390 const fields = @typeInfo(T).Struct.fields;
4391 inline for (fields, 0..) |field, i| {
4392 const int32 = ip.extra.items[i + index];
4393 @field(result, field.name) = switch (field.type) {
4394 u32 => int32,
4395 Index => @intToEnum(Index, int32),
4396 Module.Decl.Index => @intToEnum(Module.Decl.Index, int32),
4397 Module.Namespace.Index => @intToEnum(Module.Namespace.Index, int32),
4398 Module.Namespace.OptionalIndex => @intToEnum(Module.Namespace.OptionalIndex, int32),
4399 Module.Fn.Index => @intToEnum(Module.Fn.Index, int32),
4400 MapIndex => @intToEnum(MapIndex, int32),
4401 OptionalMapIndex => @intToEnum(OptionalMapIndex, int32),
4402 RuntimeIndex => @intToEnum(RuntimeIndex, int32),
4403 String => @intToEnum(String, int32),
4404 NullTerminatedString => @intToEnum(NullTerminatedString, int32),
4405 OptionalNullTerminatedString => @intToEnum(OptionalNullTerminatedString, int32),
4406 i32 => @bitCast(i32, int32),
4407 Tag.TypePointer.Flags => @bitCast(Tag.TypePointer.Flags, int32),
4408 TypeFunction.Flags => @bitCast(TypeFunction.Flags, int32),
4409 Tag.TypePointer.PackedOffset => @bitCast(Tag.TypePointer.PackedOffset, int32),
4410 Tag.TypePointer.VectorIndex => @intToEnum(Tag.TypePointer.VectorIndex, int32),
4411 Tag.Variable.Flags => @bitCast(Tag.Variable.Flags, int32),
4412 else => @compileError("bad field type: " ++ @typeName(field.type)),
4413 };
4414 }
4415 return .{
4416 .data = result,
4417 .end = index + fields.len,
4418 };
4419}
4420
4421fn extraData(ip: *const InternPool, comptime T: type, index: usize) T {
4422 return extraDataTrail(ip, T, index).data;
4423}
4424
4425/// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2.
4426fn limbData(ip: *const InternPool, comptime T: type, index: usize) T {
4427 switch (@sizeOf(Limb)) {
4428 @sizeOf(u32) => return extraData(ip, T, index),
4429 @sizeOf(u64) => {},
4430 else => @compileError("unsupported host"),
4431 }
4432 var result: T = undefined;
4433 inline for (@typeInfo(T).Struct.fields, 0..) |field, i| {
4434 const host_int = ip.limbs.items[index + i / 2];
4435 const int32 = if (i % 2 == 0)
4436 @truncate(u32, host_int)
4437 else
4438 @truncate(u32, host_int >> 32);
4439
4440 @field(result, field.name) = switch (field.type) {
4441 u32 => int32,
4442 Index => @intToEnum(Index, int32),
4443 else => @compileError("bad field type: " ++ @typeName(field.type)),
4444 };
4445 }
4446 return result;
4447}
4448
4449/// This function returns the Limb slice that is trailing data after a payload.
4450fn limbSlice(ip: *const InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb {
4451 const field_count = @typeInfo(S).Struct.fields.len;
4452 switch (@sizeOf(Limb)) {
4453 @sizeOf(u32) => {
4454 const start = limb_index + field_count;
4455 return ip.extra.items[start..][0..len];
4456 },
4457 @sizeOf(u64) => {
4458 const start = limb_index + @divExact(field_count, 2);
4459 return ip.limbs.items[start..][0..len];
4460 },
4461 else => @compileError("unsupported host"),
4462 }
4463}
4464
4465const LimbsAsIndexes = struct {
4466 start: u32,
4467 len: u32,
4468};
4469
4470fn limbsSliceToIndex(ip: *const InternPool, limbs: []const Limb) LimbsAsIndexes {
4471 const host_slice = switch (@sizeOf(Limb)) {
4472 @sizeOf(u32) => ip.extra.items,
4473 @sizeOf(u64) => ip.limbs.items,
4474 else => @compileError("unsupported host"),
4475 };
4476 // TODO: https://github.com/ziglang/zig/issues/1738
4477 return .{
4478 .start = @intCast(u32, @divExact(@ptrToInt(limbs.ptr) - @ptrToInt(host_slice.ptr), @sizeOf(Limb))),
4479 .len = @intCast(u32, limbs.len),
4480 };
4481}
4482
4483/// This function converts Limb array indexes to a primitive slice type.
4484fn limbsIndexToSlice(ip: *const InternPool, limbs: LimbsAsIndexes) []const Limb {
4485 return switch (@sizeOf(Limb)) {
4486 @sizeOf(u32) => ip.extra.items[limbs.start..][0..limbs.len],
4487 @sizeOf(u64) => ip.limbs.items[limbs.start..][0..limbs.len],
4488 else => @compileError("unsupported host"),
4489 };
4490}
4491
4492test "basic usage" {
4493 const gpa = std.testing.allocator;
4494
4495 var ip: InternPool = .{};
4496 defer ip.deinit(gpa);
4497
4498 const i32_type = try ip.get(gpa, .{ .int_type = .{
4499 .signedness = .signed,
4500 .bits = 32,
4501 } });
4502 const array_i32 = try ip.get(gpa, .{ .array_type = .{
4503 .len = 10,
4504 .child = i32_type,
4505 .sentinel = .none,
4506 } });
4507
4508 const another_i32_type = try ip.get(gpa, .{ .int_type = .{
4509 .signedness = .signed,
4510 .bits = 32,
4511 } });
4512 try std.testing.expect(another_i32_type == i32_type);
4513
4514 const another_array_i32 = try ip.get(gpa, .{ .array_type = .{
4515 .len = 10,
4516 .child = i32_type,
4517 .sentinel = .none,
4518 } });
4519 try std.testing.expect(another_array_i32 == array_i32);
4520}
4521
4522pub fn childType(ip: *const InternPool, i: Index) Index {
4523 return switch (ip.indexToKey(i)) {
4524 .ptr_type => |ptr_type| ptr_type.child,
4525 .vector_type => |vector_type| vector_type.child,
4526 .array_type => |array_type| array_type.child,
4527 .opt_type, .anyframe_type => |child| child,
4528 else => unreachable,
4529 };
4530}
4531
4532/// Given a slice type, returns the type of the ptr field.
4533pub fn slicePtrType(ip: *const InternPool, i: Index) Index {
4534 switch (i) {
4535 .slice_const_u8_type => return .manyptr_const_u8_type,
4536 .slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
4537 else => {},
4538 }
4539 const item = ip.items.get(@enumToInt(i));
4540 switch (item.tag) {
4541 .type_slice => return @intToEnum(Index, item.data),
4542 else => unreachable, // not a slice type
4543 }
4544}
4545
4546/// Given a slice value, returns the value of the ptr field.
4547pub fn slicePtr(ip: *const InternPool, i: Index) Index {
4548 const item = ip.items.get(@enumToInt(i));
4549 switch (item.tag) {
4550 .ptr_slice => return ip.extraData(PtrSlice, item.data).ptr,
4551 else => unreachable, // not a slice value
4552 }
4553}
4554
4555/// Given a slice value, returns the value of the len field.
4556pub fn sliceLen(ip: *const InternPool, i: Index) Index {
4557 const item = ip.items.get(@enumToInt(i));
4558 switch (item.tag) {
4559 .ptr_slice => return ip.extraData(PtrSlice, item.data).len,
4560 else => unreachable, // not a slice value
4561 }
4562}
4563
4564/// Given an existing value, returns the same value but with the supplied type.
4565/// Only some combinations are allowed:
4566/// * identity coercion
4567/// * undef => any
4568/// * int <=> int
4569/// * int <=> enum
4570/// * enum_literal => enum
4571/// * ptr <=> ptr
4572/// * opt ptr <=> ptr
4573/// * opt ptr <=> opt ptr
4574/// * int <=> ptr
4575/// * null_value => opt
4576/// * payload => opt
4577/// * error set <=> error set
4578/// * error union <=> error union
4579/// * error set => error union
4580/// * payload => error union
4581/// * fn <=> fn
4582pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index {
4583 const old_ty = ip.typeOf(val);
4584 if (old_ty == new_ty) return val;
4585 switch (val) {
4586 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4587 .null_value => if (ip.isOptionalType(new_ty))
4588 return ip.get(gpa, .{ .opt = .{
4589 .ty = new_ty,
4590 .val = .none,
4591 } })
4592 else if (ip.isPointerType(new_ty))
4593 return ip.get(gpa, .{ .ptr = .{
4594 .ty = new_ty,
4595 .addr = .{ .int = .zero_usize },
4596 .len = switch (ip.indexToKey(new_ty).ptr_type.flags.size) {
4597 .One, .Many, .C => .none,
4598 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4599 },
4600 } }),
4601 else => switch (ip.indexToKey(val)) {
4602 .undef => return ip.get(gpa, .{ .undef = new_ty }),
4603 .extern_func => |extern_func| if (ip.isFunctionType(new_ty))
4604 return ip.get(gpa, .{ .extern_func = .{
4605 .ty = new_ty,
4606 .decl = extern_func.decl,
4607 .lib_name = extern_func.lib_name,
4608 } }),
4609 .func => |func| if (ip.isFunctionType(new_ty))
4610 return ip.get(gpa, .{ .func = .{
4611 .ty = new_ty,
4612 .index = func.index,
4613 } }),
4614 .int => |int| switch (ip.indexToKey(new_ty)) {
4615 .enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
4616 .ty = new_ty,
4617 .int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
4618 } }),
4619 .ptr_type => return ip.get(gpa, .{ .ptr = .{
4620 .ty = new_ty,
4621 .addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
4622 } }),
4623 else => if (ip.isIntegerType(new_ty))
4624 return getCoercedInts(ip, gpa, int, new_ty),
4625 },
4626 .enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
4627 return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
4628 .enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
4629 .enum_type => |enum_type| {
4630 const index = enum_type.nameIndex(ip, enum_literal).?;
4631 return ip.get(gpa, .{ .enum_tag = .{
4632 .ty = new_ty,
4633 .int = if (enum_type.values.len != 0)
4634 enum_type.values[index]
4635 else
4636 try ip.get(gpa, .{ .int = .{
4637 .ty = enum_type.tag_ty,
4638 .storage = .{ .u64 = index },
4639 } }),
4640 } });
4641 },
4642 else => {},
4643 },
4644 .ptr => |ptr| if (ip.isPointerType(new_ty))
4645 return ip.get(gpa, .{ .ptr = .{
4646 .ty = new_ty,
4647 .addr = ptr.addr,
4648 .len = ptr.len,
4649 } })
4650 else if (ip.isIntegerType(new_ty))
4651 switch (ptr.addr) {
4652 .int => |int| return ip.getCoerced(gpa, int, new_ty),
4653 else => {},
4654 },
4655 .opt => |opt| switch (ip.indexToKey(new_ty)) {
4656 .ptr_type => |ptr_type| return switch (opt.val) {
4657 .none => try ip.get(gpa, .{ .ptr = .{
4658 .ty = new_ty,
4659 .addr = .{ .int = .zero_usize },
4660 .len = switch (ptr_type.flags.size) {
4661 .One, .Many, .C => .none,
4662 .Slice => try ip.get(gpa, .{ .undef = .usize_type }),
4663 },
4664 } }),
4665 else => |payload| try ip.getCoerced(gpa, payload, new_ty),
4666 },
4667 .opt_type => |child_type| return try ip.get(gpa, .{ .opt = .{
4668 .ty = new_ty,
4669 .val = switch (opt.val) {
4670 .none => .none,
4671 else => try ip.getCoerced(gpa, opt.val, child_type),
4672 },
4673 } }),
4674 else => {},
4675 },
4676 .err => |err| if (ip.isErrorSetType(new_ty))
4677 return ip.get(gpa, .{ .err = .{
4678 .ty = new_ty,
4679 .name = err.name,
4680 } })
4681 else if (ip.isErrorUnionType(new_ty))
4682 return ip.get(gpa, .{ .error_union = .{
4683 .ty = new_ty,
4684 .val = .{ .err_name = err.name },
4685 } }),
4686 .error_union => |error_union| if (ip.isErrorUnionType(new_ty))
4687 return ip.get(gpa, .{ .error_union = .{
4688 .ty = new_ty,
4689 .val = error_union.val,
4690 } }),
4691 else => {},
4692 },
4693 }
4694 switch (ip.indexToKey(new_ty)) {
4695 .opt_type => |child_type| switch (val) {
4696 .null_value => return ip.get(gpa, .{ .opt = .{
4697 .ty = new_ty,
4698 .val = .none,
4699 } }),
4700 else => return ip.get(gpa, .{ .opt = .{
4701 .ty = new_ty,
4702 .val = try ip.getCoerced(gpa, val, child_type),
4703 } }),
4704 },
4705 .error_union_type => |error_union_type| return ip.get(gpa, .{ .error_union = .{
4706 .ty = new_ty,
4707 .val = .{ .payload = try ip.getCoerced(gpa, val, error_union_type.payload_type) },
4708 } }),
4709 else => {},
4710 }
4711 if (std.debug.runtime_safety) {
4712 std.debug.panic("InternPool.getCoerced of {s} not implemented from {s} to {s}", .{
4713 @tagName(ip.indexToKey(val)),
4714 @tagName(ip.indexToKey(old_ty)),
4715 @tagName(ip.indexToKey(new_ty)),
4716 });
4717 }
4718 unreachable;
4719}
4720
4721/// Asserts `val` has an integer type.
4722/// Assumes `new_ty` is an integer type.
4723pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Index) Allocator.Error!Index {
4724 // The key cannot be passed directly to `get`, otherwise in the case of
4725 // big_int storage, the limbs would be invalidated before they are read.
4726 // Here we pre-reserve the limbs to ensure that the logic in `addInt` will
4727 // not use an invalidated limbs pointer.
4728 const new_storage: Key.Int.Storage = switch (int.storage) {
4729 .u64, .i64, .lazy_align, .lazy_size => int.storage,
4730 .big_int => |big_int| storage: {
4731 const positive = big_int.positive;
4732 const limbs = ip.limbsSliceToIndex(big_int.limbs);
4733 // This line invalidates the limbs slice, but the indexes computed in the
4734 // previous line are still correct.
4735 try reserveLimbs(ip, gpa, @typeInfo(Int).Struct.fields.len + big_int.limbs.len);
4736 break :storage .{ .big_int = .{
4737 .limbs = ip.limbsIndexToSlice(limbs),
4738 .positive = positive,
4739 } };
4740 },
4741 };
4742 return ip.get(gpa, .{ .int = .{
4743 .ty = new_ty,
4744 .storage = new_storage,
4745 } });
4746}
4747
4748pub fn indexToStructType(ip: *const InternPool, val: Index) Module.Struct.OptionalIndex {
4749 assert(val != .none);
4750 const tags = ip.items.items(.tag);
4751 if (tags[@enumToInt(val)] != .type_struct) return .none;
4752 const datas = ip.items.items(.data);
4753 return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional();
4754}
4755
4756pub fn indexToUnionType(ip: *const InternPool, val: Index) Module.Union.OptionalIndex {
4757 assert(val != .none);
4758 const tags = ip.items.items(.tag);
4759 switch (tags[@enumToInt(val)]) {
4760 .type_union_tagged, .type_union_untagged, .type_union_safety => {},
4761 else => return .none,
4762 }
4763 const datas = ip.items.items(.data);
4764 return @intToEnum(Module.Union.Index, datas[@enumToInt(val)]).toOptional();
4765}
4766
4767pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {
4768 assert(val != .none);
4769 const tags = ip.items.items(.tag);
4770 const datas = ip.items.items(.data);
4771 switch (tags[@enumToInt(val)]) {
4772 .type_function => return indexToKeyFuncType(ip, datas[@enumToInt(val)]),
4773 else => return null,
4774 }
4775}
4776
4777pub fn indexToFunc(ip: *const InternPool, val: Index) Module.Fn.OptionalIndex {
4778 assert(val != .none);
4779 const tags = ip.items.items(.tag);
4780 if (tags[@enumToInt(val)] != .func) return .none;
4781 const datas = ip.items.items(.data);
4782 return ip.extraData(Tag.Func, datas[@enumToInt(val)]).index.toOptional();
4783}
4784
4785pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
4786 assert(val != .none);
4787 const tags = ip.items.items(.tag);
4788 if (tags[@enumToInt(val)] != .type_inferred_error_set) return .none;
4789 const datas = ip.items.items(.data);
4790 return @intToEnum(Module.Fn.InferredErrorSet.Index, datas[@enumToInt(val)]).toOptional();
4791}
4792
4793/// includes .comptime_int_type
4794pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {
4795 return switch (ty) {
4796 .usize_type,
4797 .isize_type,
4798 .c_char_type,
4799 .c_short_type,
4800 .c_ushort_type,
4801 .c_int_type,
4802 .c_uint_type,
4803 .c_long_type,
4804 .c_ulong_type,
4805 .c_longlong_type,
4806 .c_ulonglong_type,
4807 .c_longdouble_type,
4808 .comptime_int_type,
4809 => true,
4810 else => ip.indexToKey(ty) == .int_type,
4811 };
4812}
4813
4814/// does not include .enum_literal_type
4815pub fn isEnumType(ip: *const InternPool, ty: Index) bool {
4816 return switch (ty) {
4817 .atomic_order_type,
4818 .atomic_rmw_op_type,
4819 .calling_convention_type,
4820 .address_space_type,
4821 .float_mode_type,
4822 .reduce_op_type,
4823 .call_modifier_type,
4824 => true,
4825 else => ip.indexToKey(ty) == .enum_type,
4826 };
4827}
4828
4829pub fn isFunctionType(ip: *const InternPool, ty: Index) bool {
4830 return ip.indexToKey(ty) == .func_type;
4831}
4832
4833pub fn isPointerType(ip: *const InternPool, ty: Index) bool {
4834 return ip.indexToKey(ty) == .ptr_type;
4835}
4836
4837pub fn isOptionalType(ip: *const InternPool, ty: Index) bool {
4838 return ip.indexToKey(ty) == .opt_type;
4839}
4840
4841/// includes .inferred_error_set_type
4842pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool {
4843 return ty == .anyerror_type or switch (ip.indexToKey(ty)) {
4844 .error_set_type, .inferred_error_set_type => true,
4845 else => false,
4846 };
4847}
4848
4849pub fn isInferredErrorSetType(ip: *const InternPool, ty: Index) bool {
4850 return ip.indexToKey(ty) == .inferred_error_set_type;
4851}
4852
4853pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {
4854 return ip.indexToKey(ty) == .error_union_type;
4855}
4856
4857pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {
4858 return switch (ip.indexToKey(ty)) {
4859 .array_type, .vector_type, .anon_struct_type, .struct_type => true,
4860 else => false,
4861 };
4862}
4863
4864/// The is only legal because the initializer is not part of the hash.
4865pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {
4866 const item = ip.items.get(@enumToInt(index));
4867 assert(item.tag == .variable);
4868 ip.extra.items[item.data + std.meta.fieldIndex(Tag.Variable, "init").?] = @enumToInt(init_index);
4869}
4870
4871pub fn dump(ip: *const InternPool) void {
4872 dumpStatsFallible(ip, std.heap.page_allocator) catch return;
4873 dumpAllFallible(ip) catch return;
4874}
4875
4876fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
4877 const items_size = (1 + 4) * ip.items.len;
4878 const extra_size = 4 * ip.extra.items.len;
4879 const limbs_size = 8 * ip.limbs.items.len;
4880 // TODO: fields size is not taken into account
4881 const structs_size = ip.allocated_structs.len *
4882 (@sizeOf(Module.Struct) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4883 const unions_size = ip.allocated_unions.len *
4884 (@sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl));
4885 const funcs_size = ip.allocated_funcs.len *
4886 (@sizeOf(Module.Fn) + @sizeOf(Module.Decl));
4887
4888 // TODO: map overhead size is not taken into account
4889 const total_size = @sizeOf(InternPool) + items_size + extra_size + limbs_size +
4890 structs_size + unions_size + funcs_size;
4891
4892 std.debug.print(
4893 \\InternPool size: {d} bytes
4894 \\ {d} items: {d} bytes
4895 \\ {d} extra: {d} bytes
4896 \\ {d} limbs: {d} bytes
4897 \\ {d} structs: {d} bytes
4898 \\ {d} unions: {d} bytes
4899 \\ {d} funcs: {d} bytes
4900 \\
4901 , .{
4902 total_size,
4903 ip.items.len,
4904 items_size,
4905 ip.extra.items.len,
4906 extra_size,
4907 ip.limbs.items.len,
4908 limbs_size,
4909 ip.allocated_structs.len,
4910 structs_size,
4911 ip.allocated_unions.len,
4912 unions_size,
4913 ip.allocated_funcs.len,
4914 funcs_size,
4915 });
4916
4917 const tags = ip.items.items(.tag);
4918 const datas = ip.items.items(.data);
4919 const TagStats = struct {
4920 count: usize = 0,
4921 bytes: usize = 0,
4922 };
4923 var counts = std.AutoArrayHashMap(Tag, TagStats).init(arena);
4924 for (tags, datas) |tag, data| {
4925 const gop = try counts.getOrPut(tag);
4926 if (!gop.found_existing) gop.value_ptr.* = .{};
4927 gop.value_ptr.count += 1;
4928 gop.value_ptr.bytes += 1 + 4 + @as(usize, switch (tag) {
4929 .type_int_signed => 0,
4930 .type_int_unsigned => 0,
4931 .type_array_small => @sizeOf(Vector),
4932 .type_array_big => @sizeOf(Array),
4933 .type_vector => @sizeOf(Vector),
4934 .type_pointer => @sizeOf(Tag.TypePointer),
4935 .type_slice => 0,
4936 .type_optional => 0,
4937 .type_anyframe => 0,
4938 .type_error_union => @sizeOf(Key.ErrorUnionType),
4939 .type_error_set => b: {
4940 const info = ip.extraData(ErrorSet, data);
4941 break :b @sizeOf(ErrorSet) + (@sizeOf(u32) * info.names_len);
4942 },
4943 .type_inferred_error_set => @sizeOf(Module.Fn.InferredErrorSet),
4944 .type_enum_explicit, .type_enum_nonexhaustive => @sizeOf(EnumExplicit),
4945 .type_enum_auto => @sizeOf(EnumAuto),
4946 .type_opaque => @sizeOf(Key.OpaqueType),
4947 .type_struct => b: {
4948 const struct_index = @intToEnum(Module.Struct.Index, data);
4949 const struct_obj = ip.structPtrConst(struct_index);
4950 break :b @sizeOf(Module.Struct) +
4951 @sizeOf(Module.Namespace) +
4952 @sizeOf(Module.Decl) +
4953 (struct_obj.fields.count() * @sizeOf(Module.Struct.Field));
4954 },
4955 .type_struct_ns => @sizeOf(Module.Namespace),
4956 .type_struct_anon => b: {
4957 const info = ip.extraData(TypeStructAnon, data);
4958 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 3 * info.fields_len);
4959 },
4960 .type_tuple_anon => b: {
4961 const info = ip.extraData(TypeStructAnon, data);
4962 break :b @sizeOf(TypeStructAnon) + (@sizeOf(u32) * 2 * info.fields_len);
4963 },
4964
4965 .type_union_tagged,
4966 .type_union_untagged,
4967 .type_union_safety,
4968 => @sizeOf(Module.Union) + @sizeOf(Module.Namespace) + @sizeOf(Module.Decl),
4969
4970 .type_function => b: {
4971 const info = ip.extraData(TypeFunction, data);
4972 break :b @sizeOf(TypeFunction) + (@sizeOf(Index) * info.params_len);
4973 },
4974
4975 .undef => 0,
4976 .runtime_value => @sizeOf(Tag.TypeValue),
4977 .simple_type => 0,
4978 .simple_value => 0,
4979 .ptr_decl => @sizeOf(PtrDecl),
4980 .ptr_mut_decl => @sizeOf(PtrMutDecl),
4981 .ptr_comptime_field => @sizeOf(PtrComptimeField),
4982 .ptr_int => @sizeOf(PtrBase),
4983 .ptr_eu_payload => @sizeOf(PtrBase),
4984 .ptr_opt_payload => @sizeOf(PtrBase),
4985 .ptr_elem => @sizeOf(PtrBaseIndex),
4986 .ptr_field => @sizeOf(PtrBaseIndex),
4987 .ptr_slice => @sizeOf(PtrSlice),
4988 .opt_null => 0,
4989 .opt_payload => @sizeOf(Tag.TypeValue),
4990 .int_u8 => 0,
4991 .int_u16 => 0,
4992 .int_u32 => 0,
4993 .int_i32 => 0,
4994 .int_usize => 0,
4995 .int_comptime_int_u32 => 0,
4996 .int_comptime_int_i32 => 0,
4997 .int_small => @sizeOf(IntSmall),
4998
4999 .int_positive,
5000 .int_negative,
5001 => b: {
5002 const int = ip.limbData(Int, data);
5003 break :b @sizeOf(Int) + int.limbs_len * 8;
5004 },
5005
5006 .int_lazy_align, .int_lazy_size => @sizeOf(IntLazy),
5007
5008 .error_set_error, .error_union_error => @sizeOf(Key.Error),
5009 .error_union_payload => @sizeOf(Tag.TypeValue),
5010 .enum_literal => 0,
5011 .enum_tag => @sizeOf(Tag.EnumTag),
5012
5013 .bytes => b: {
5014 const info = ip.extraData(Bytes, data);
5015 const len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(info.ty));
5016 break :b @sizeOf(Bytes) + len +
5017 @boolToInt(ip.string_bytes.items[@enumToInt(info.bytes) + len - 1] != 0);
5018 },
5019 .aggregate => b: {
5020 const info = ip.extraData(Tag.Aggregate, data);
5021 const fields_len = @intCast(u32, ip.aggregateTypeLenIncludingSentinel(info.ty));
5022 break :b @sizeOf(Tag.Aggregate) + (@sizeOf(Index) * fields_len);
5023 },
5024 .repeated => @sizeOf(Repeated),
5025
5026 .float_f16 => 0,
5027 .float_f32 => 0,
5028 .float_f64 => @sizeOf(Float64),
5029 .float_f80 => @sizeOf(Float80),
5030 .float_f128 => @sizeOf(Float128),
5031 .float_c_longdouble_f80 => @sizeOf(Float80),
5032 .float_c_longdouble_f128 => @sizeOf(Float128),
5033 .float_comptime_float => @sizeOf(Float128),
5034 .variable => @sizeOf(Tag.Variable) + @sizeOf(Module.Decl),
5035 .extern_func => @sizeOf(Tag.ExternFunc) + @sizeOf(Module.Decl),
5036 .func => @sizeOf(Tag.Func) + @sizeOf(Module.Fn) + @sizeOf(Module.Decl),
5037 .only_possible_value => 0,
5038 .union_value => @sizeOf(Key.Union),
5039
5040 .memoized_call => b: {
5041 const info = ip.extraData(MemoizedCall, data);
5042 break :b @sizeOf(MemoizedCall) + (@sizeOf(Index) * info.args_len);
5043 },
5044 });
5045 }
5046 const SortContext = struct {
5047 map: *std.AutoArrayHashMap(Tag, TagStats),
5048 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
5049 const values = ctx.map.values();
5050 return values[a_index].bytes > values[b_index].bytes;
5051 //return values[a_index].count > values[b_index].count;
5052 }
5053 };
5054 counts.sort(SortContext{ .map = &counts });
5055 const len = @min(50, counts.count());
5056 std.debug.print(" top 50 tags:\n", .{});
5057 for (counts.keys()[0..len], counts.values()[0..len]) |tag, stats| {
5058 std.debug.print(" {s}: {d} occurrences, {d} total bytes\n", .{
5059 @tagName(tag), stats.count, stats.bytes,
5060 });
5061 }
5062}
5063
5064fn dumpAllFallible(ip: *const InternPool) anyerror!void {
5065 const tags = ip.items.items(.tag);
5066 const datas = ip.items.items(.data);
5067 var bw = std.io.bufferedWriter(std.io.getStdErr().writer());
5068 const w = bw.writer();
5069 for (tags, datas, 0..) |tag, data, i| {
5070 try w.print("${d} = {s}(", .{ i, @tagName(tag) });
5071 switch (tag) {
5072 .simple_type => try w.print("{s}", .{@tagName(@intToEnum(SimpleType, data))}),
5073 .simple_value => try w.print("{s}", .{@tagName(@intToEnum(SimpleValue, data))}),
5074
5075 .type_int_signed,
5076 .type_int_unsigned,
5077 .type_array_small,
5078 .type_array_big,
5079 .type_vector,
5080 .type_pointer,
5081 .type_optional,
5082 .type_anyframe,
5083 .type_error_union,
5084 .type_error_set,
5085 .type_inferred_error_set,
5086 .type_enum_explicit,
5087 .type_enum_nonexhaustive,
5088 .type_enum_auto,
5089 .type_opaque,
5090 .type_struct,
5091 .type_struct_ns,
5092 .type_struct_anon,
5093 .type_tuple_anon,
5094 .type_union_tagged,
5095 .type_union_untagged,
5096 .type_union_safety,
5097 .type_function,
5098 .undef,
5099 .runtime_value,
5100 .ptr_decl,
5101 .ptr_mut_decl,
5102 .ptr_comptime_field,
5103 .ptr_int,
5104 .ptr_eu_payload,
5105 .ptr_opt_payload,
5106 .ptr_elem,
5107 .ptr_field,
5108 .ptr_slice,
5109 .opt_payload,
5110 .int_u8,
5111 .int_u16,
5112 .int_u32,
5113 .int_i32,
5114 .int_usize,
5115 .int_comptime_int_u32,
5116 .int_comptime_int_i32,
5117 .int_small,
5118 .int_positive,
5119 .int_negative,
5120 .int_lazy_align,
5121 .int_lazy_size,
5122 .error_set_error,
5123 .error_union_error,
5124 .error_union_payload,
5125 .enum_literal,
5126 .enum_tag,
5127 .bytes,
5128 .aggregate,
5129 .repeated,
5130 .float_f16,
5131 .float_f32,
5132 .float_f64,
5133 .float_f80,
5134 .float_f128,
5135 .float_c_longdouble_f80,
5136 .float_c_longdouble_f128,
5137 .float_comptime_float,
5138 .variable,
5139 .extern_func,
5140 .func,
5141 .union_value,
5142 .memoized_call,
5143 => try w.print("{d}", .{data}),
5144
5145 .opt_null,
5146 .type_slice,
5147 .only_possible_value,
5148 => try w.print("${d}", .{data}),
5149 }
5150 try w.writeAll(")\n");
5151 }
5152 try bw.flush();
5153}
5154
5155pub fn structPtr(ip: *InternPool, index: Module.Struct.Index) *Module.Struct {
5156 return ip.allocated_structs.at(@enumToInt(index));
5157}
5158
5159pub fn structPtrConst(ip: *const InternPool, index: Module.Struct.Index) *const Module.Struct {
5160 return ip.allocated_structs.at(@enumToInt(index));
5161}
5162
5163pub fn structPtrUnwrapConst(ip: *const InternPool, index: Module.Struct.OptionalIndex) ?*const Module.Struct {
5164 return structPtrConst(ip, index.unwrap() orelse return null);
5165}
5166
5167pub fn unionPtr(ip: *InternPool, index: Module.Union.Index) *Module.Union {
5168 return ip.allocated_unions.at(@enumToInt(index));
5169}
5170
5171pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Module.Union {
5172 return ip.allocated_unions.at(@enumToInt(index));
5173}
5174
5175pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {
5176 return ip.allocated_funcs.at(@enumToInt(index));
5177}
5178
5179pub fn funcPtrConst(ip: *const InternPool, index: Module.Fn.Index) *const Module.Fn {
5180 return ip.allocated_funcs.at(@enumToInt(index));
5181}
5182
5183pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
5184 return ip.allocated_inferred_error_sets.at(@enumToInt(index));
5185}
5186
5187pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet {
5188 return ip.allocated_inferred_error_sets.at(@enumToInt(index));
5189}
5190
5191pub fn createStruct(
5192 ip: *InternPool,
5193 gpa: Allocator,
5194 initialization: Module.Struct,
5195) Allocator.Error!Module.Struct.Index {
5196 if (ip.structs_free_list.popOrNull()) |index| {
5197 ip.allocated_structs.at(@enumToInt(index)).* = initialization;
5198 return index;
5199 }
5200 const ptr = try ip.allocated_structs.addOne(gpa);
5201 ptr.* = initialization;
5202 return @intToEnum(Module.Struct.Index, ip.allocated_structs.len - 1);
5203}
5204
5205pub fn destroyStruct(ip: *InternPool, gpa: Allocator, index: Module.Struct.Index) void {
5206 ip.structPtr(index).* = undefined;
5207 ip.structs_free_list.append(gpa, index) catch {
5208 // In order to keep `destroyStruct` a non-fallible function, we ignore memory
5209 // allocation failures here, instead leaking the Struct until garbage collection.
5210 };
5211}
5212
5213pub fn createUnion(
5214 ip: *InternPool,
5215 gpa: Allocator,
5216 initialization: Module.Union,
5217) Allocator.Error!Module.Union.Index {
5218 if (ip.unions_free_list.popOrNull()) |index| {
5219 ip.allocated_unions.at(@enumToInt(index)).* = initialization;
5220 return index;
5221 }
5222 const ptr = try ip.allocated_unions.addOne(gpa);
5223 ptr.* = initialization;
5224 return @intToEnum(Module.Union.Index, ip.allocated_unions.len - 1);
5225}
5226
5227pub fn destroyUnion(ip: *InternPool, gpa: Allocator, index: Module.Union.Index) void {
5228 ip.unionPtr(index).* = undefined;
5229 ip.unions_free_list.append(gpa, index) catch {
5230 // In order to keep `destroyUnion` a non-fallible function, we ignore memory
5231 // allocation failures here, instead leaking the Union until garbage collection.
5232 };
5233}
5234
5235pub fn createFunc(
5236 ip: *InternPool,
5237 gpa: Allocator,
5238 initialization: Module.Fn,
5239) Allocator.Error!Module.Fn.Index {
5240 if (ip.funcs_free_list.popOrNull()) |index| {
5241 ip.allocated_funcs.at(@enumToInt(index)).* = initialization;
5242 return index;
5243 }
5244 const ptr = try ip.allocated_funcs.addOne(gpa);
5245 ptr.* = initialization;
5246 return @intToEnum(Module.Fn.Index, ip.allocated_funcs.len - 1);
5247}
5248
5249pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void {
5250 ip.funcPtr(index).* = undefined;
5251 ip.funcs_free_list.append(gpa, index) catch {
5252 // In order to keep `destroyFunc` a non-fallible function, we ignore memory
5253 // allocation failures here, instead leaking the Fn until garbage collection.
5254 };
5255}
5256
5257pub fn createInferredErrorSet(
5258 ip: *InternPool,
5259 gpa: Allocator,
5260 initialization: Module.Fn.InferredErrorSet,
5261) Allocator.Error!Module.Fn.InferredErrorSet.Index {
5262 if (ip.inferred_error_sets_free_list.popOrNull()) |index| {
5263 ip.allocated_inferred_error_sets.at(@enumToInt(index)).* = initialization;
5264 return index;
5265 }
5266 const ptr = try ip.allocated_inferred_error_sets.addOne(gpa);
5267 ptr.* = initialization;
5268 return @intToEnum(Module.Fn.InferredErrorSet.Index, ip.allocated_inferred_error_sets.len - 1);
5269}
5270
5271pub fn destroyInferredErrorSet(ip: *InternPool, gpa: Allocator, index: Module.Fn.InferredErrorSet.Index) void {
5272 ip.inferredErrorSetPtr(index).* = undefined;
5273 ip.inferred_error_sets_free_list.append(gpa, index) catch {
5274 // In order to keep `destroyInferredErrorSet` a non-fallible function, we ignore memory
5275 // allocation failures here, instead leaking the InferredErrorSet until garbage collection.
5276 };
5277}
5278
5279pub fn getOrPutString(
5280 ip: *InternPool,
5281 gpa: Allocator,
5282 s: []const u8,
5283) Allocator.Error!NullTerminatedString {
5284 try ip.string_bytes.ensureUnusedCapacity(gpa, s.len + 1);
5285 ip.string_bytes.appendSliceAssumeCapacity(s);
5286 ip.string_bytes.appendAssumeCapacity(0);
5287 return ip.getOrPutTrailingString(gpa, s.len + 1);
5288}
5289
5290pub fn getOrPutStringFmt(
5291 ip: *InternPool,
5292 gpa: Allocator,
5293 comptime format: []const u8,
5294 args: anytype,
5295) Allocator.Error!NullTerminatedString {
5296 // ensure that references to string_bytes in args do not get invalidated
5297 const len = @intCast(usize, std.fmt.count(format, args) + 1);
5298 try ip.string_bytes.ensureUnusedCapacity(gpa, len);
5299 ip.string_bytes.writer(undefined).print(format, args) catch unreachable;
5300 ip.string_bytes.appendAssumeCapacity(0);
5301 return ip.getOrPutTrailingString(gpa, len);
5302}
5303
5304pub fn getOrPutStringOpt(
5305 ip: *InternPool,
5306 gpa: Allocator,
5307 optional_string: ?[]const u8,
5308) Allocator.Error!OptionalNullTerminatedString {
5309 const s = optional_string orelse return .none;
5310 const interned = try getOrPutString(ip, gpa, s);
5311 return interned.toOptional();
5312}
5313
5314/// Uses the last len bytes of ip.string_bytes as the key.
5315pub fn getOrPutTrailingString(
5316 ip: *InternPool,
5317 gpa: Allocator,
5318 len: usize,
5319) Allocator.Error!NullTerminatedString {
5320 const string_bytes = &ip.string_bytes;
5321 const str_index = @intCast(u32, string_bytes.items.len - len);
5322 if (len > 0 and string_bytes.getLast() == 0) {
5323 _ = string_bytes.pop();
5324 } else {
5325 try string_bytes.ensureUnusedCapacity(gpa, 1);
5326 }
5327 const key: []const u8 = string_bytes.items[str_index..];
5328 const gop = try ip.string_table.getOrPutContextAdapted(gpa, key, std.hash_map.StringIndexAdapter{
5329 .bytes = string_bytes,
5330 }, std.hash_map.StringIndexContext{
5331 .bytes = string_bytes,
5332 });
5333 if (gop.found_existing) {
5334 string_bytes.shrinkRetainingCapacity(str_index);
5335 return @intToEnum(NullTerminatedString, gop.key_ptr.*);
5336 } else {
5337 gop.key_ptr.* = str_index;
5338 string_bytes.appendAssumeCapacity(0);
5339 return @intToEnum(NullTerminatedString, str_index);
5340 }
5341}
5342
5343pub fn getString(ip: *InternPool, s: []const u8) OptionalNullTerminatedString {
5344 if (ip.string_table.getKeyAdapted(s, std.hash_map.StringIndexAdapter{
5345 .bytes = &ip.string_bytes,
5346 })) |index| {
5347 return @intToEnum(NullTerminatedString, index).toOptional();
5348 } else {
5349 return .none;
5350 }
5351}
5352
5353pub fn stringToSlice(ip: *const InternPool, s: NullTerminatedString) [:0]const u8 {
5354 const string_bytes = ip.string_bytes.items;
5355 const start = @enumToInt(s);
5356 var end: usize = start;
5357 while (string_bytes[end] != 0) end += 1;
5358 return string_bytes[start..end :0];
5359}
5360
5361pub fn stringToSliceUnwrap(ip: *const InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 {
5362 return ip.stringToSlice(s.unwrap() orelse return null);
5363}
5364
5365pub fn stringEqlSlice(ip: *const InternPool, a: NullTerminatedString, b: []const u8) bool {
5366 return std.mem.eql(u8, stringToSlice(ip, a), b);
5367}
5368
5369pub fn typeOf(ip: *const InternPool, index: Index) Index {
5370 // This optimization of static keys is required so that typeOf can be called
5371 // on static keys that haven't been added yet during static key initialization.
5372 // An alternative would be to topological sort the static keys, but this would
5373 // mean that the range of type indices would not be dense.
5374 return switch (index) {
5375 .u1_type,
5376 .u8_type,
5377 .i8_type,
5378 .u16_type,
5379 .i16_type,
5380 .u29_type,
5381 .u32_type,
5382 .i32_type,
5383 .u64_type,
5384 .i64_type,
5385 .u80_type,
5386 .u128_type,
5387 .i128_type,
5388 .usize_type,
5389 .isize_type,
5390 .c_char_type,
5391 .c_short_type,
5392 .c_ushort_type,
5393 .c_int_type,
5394 .c_uint_type,
5395 .c_long_type,
5396 .c_ulong_type,
5397 .c_longlong_type,
5398 .c_ulonglong_type,
5399 .c_longdouble_type,
5400 .f16_type,
5401 .f32_type,
5402 .f64_type,
5403 .f80_type,
5404 .f128_type,
5405 .anyopaque_type,
5406 .bool_type,
5407 .void_type,
5408 .type_type,
5409 .anyerror_type,
5410 .comptime_int_type,
5411 .comptime_float_type,
5412 .noreturn_type,
5413 .anyframe_type,
5414 .null_type,
5415 .undefined_type,
5416 .enum_literal_type,
5417 .atomic_order_type,
5418 .atomic_rmw_op_type,
5419 .calling_convention_type,
5420 .address_space_type,
5421 .float_mode_type,
5422 .reduce_op_type,
5423 .call_modifier_type,
5424 .prefetch_options_type,
5425 .export_options_type,
5426 .extern_options_type,
5427 .type_info_type,
5428 .manyptr_u8_type,
5429 .manyptr_const_u8_type,
5430 .manyptr_const_u8_sentinel_0_type,
5431 .single_const_pointer_to_comptime_int_type,
5432 .slice_const_u8_type,
5433 .slice_const_u8_sentinel_0_type,
5434 .anyerror_void_error_union_type,
5435 .generic_poison_type,
5436 .empty_struct_type,
5437 => .type_type,
5438
5439 .undef => .undefined_type,
5440 .zero, .one, .negative_one => .comptime_int_type,
5441 .zero_usize, .one_usize => .usize_type,
5442 .zero_u8, .one_u8, .four_u8 => .u8_type,
5443 .calling_convention_c, .calling_convention_inline => .calling_convention_type,
5444 .void_value => .void_type,
5445 .unreachable_value => .noreturn_type,
5446 .null_value => .null_type,
5447 .bool_true, .bool_false => .bool_type,
5448 .empty_struct => .empty_struct_type,
5449 .generic_poison => .generic_poison_type,
5450
5451 // This optimization on tags is needed so that indexToKey can call
5452 // typeOf without being recursive.
5453 _ => switch (ip.items.items(.tag)[@enumToInt(index)]) {
5454 .type_int_signed,
5455 .type_int_unsigned,
5456 .type_array_big,
5457 .type_array_small,
5458 .type_vector,
5459 .type_pointer,
5460 .type_slice,
5461 .type_optional,
5462 .type_anyframe,
5463 .type_error_union,
5464 .type_error_set,
5465 .type_inferred_error_set,
5466 .type_enum_auto,
5467 .type_enum_explicit,
5468 .type_enum_nonexhaustive,
5469 .simple_type,
5470 .type_opaque,
5471 .type_struct,
5472 .type_struct_ns,
5473 .type_struct_anon,
5474 .type_tuple_anon,
5475 .type_union_tagged,
5476 .type_union_untagged,
5477 .type_union_safety,
5478 .type_function,
5479 => .type_type,
5480
5481 .undef,
5482 .opt_null,
5483 .only_possible_value,
5484 => @intToEnum(Index, ip.items.items(.data)[@enumToInt(index)]),
5485
5486 .simple_value => unreachable, // handled via Index above
5487
5488 inline .ptr_decl,
5489 .ptr_mut_decl,
5490 .ptr_comptime_field,
5491 .ptr_int,
5492 .ptr_eu_payload,
5493 .ptr_opt_payload,
5494 .ptr_elem,
5495 .ptr_field,
5496 .ptr_slice,
5497 .opt_payload,
5498 .error_union_payload,
5499 .runtime_value,
5500 .int_small,
5501 .int_lazy_align,
5502 .int_lazy_size,
5503 .error_set_error,
5504 .error_union_error,
5505 .enum_tag,
5506 .variable,
5507 .extern_func,
5508 .func,
5509 .union_value,
5510 .bytes,
5511 .aggregate,
5512 .repeated,
5513 => |t| {
5514 const extra_index = ip.items.items(.data)[@enumToInt(index)];
5515 const field_index = std.meta.fieldIndex(t.Payload(), "ty").?;
5516 return @intToEnum(Index, ip.extra.items[extra_index + field_index]);
5517 },
5518
5519 .int_u8 => .u8_type,
5520 .int_u16 => .u16_type,
5521 .int_u32 => .u32_type,
5522 .int_i32 => .i32_type,
5523 .int_usize => .usize_type,
5524
5525 .int_comptime_int_u32,
5526 .int_comptime_int_i32,
5527 => .comptime_int_type,
5528
5529 // Note these are stored in limbs data, not extra data.
5530 .int_positive,
5531 .int_negative,
5532 => ip.limbData(Int, ip.items.items(.data)[@enumToInt(index)]).ty,
5533
5534 .enum_literal => .enum_literal_type,
5535 .float_f16 => .f16_type,
5536 .float_f32 => .f32_type,
5537 .float_f64 => .f64_type,
5538 .float_f80 => .f80_type,
5539 .float_f128 => .f128_type,
5540
5541 .float_c_longdouble_f80,
5542 .float_c_longdouble_f128,
5543 => .c_longdouble_type,
5544
5545 .float_comptime_float => .comptime_float_type,
5546
5547 .memoized_call => unreachable,
5548 },
5549
5550 .var_args_param_type => unreachable,
5551 .none => unreachable,
5552 };
5553}
5554
5555/// Assumes that the enum's field indexes equal its value tags.
5556pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
5557 const int = ip.indexToKey(i).enum_tag.int;
5558 return @intToEnum(E, ip.indexToKey(int).int.storage.u64);
5559}
5560
5561pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
5562 return switch (ip.indexToKey(ty)) {
5563 .struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
5564 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
5565 .array_type => |array_type| array_type.len,
5566 .vector_type => |vector_type| vector_type.len,
5567 else => unreachable,
5568 };
5569}
5570
5571pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
5572 return switch (ip.indexToKey(ty)) {
5573 .struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
5574 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
5575 .array_type => |array_type| array_type.len + @boolToInt(array_type.sentinel != .none),
5576 .vector_type => |vector_type| vector_type.len,
5577 else => unreachable,
5578 };
5579}
5580
5581pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
5582 return switch (ty) {
5583 .noreturn_type => true,
5584 else => switch (ip.indexToKey(ty)) {
5585 .error_set_type => |error_set_type| error_set_type.names.len == 0,
5586 else => false,
5587 },
5588 };
5589}
5590
5591/// This is a particularly hot function, so we operate directly on encodings
5592/// rather than the more straightforward implementation of calling `indexToKey`.
5593pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
5594 return switch (index) {
5595 .u1_type,
5596 .u8_type,
5597 .i8_type,
5598 .u16_type,
5599 .i16_type,
5600 .u29_type,
5601 .u32_type,
5602 .i32_type,
5603 .u64_type,
5604 .i64_type,
5605 .u80_type,
5606 .u128_type,
5607 .i128_type,
5608 .usize_type,
5609 .isize_type,
5610 .c_char_type,
5611 .c_short_type,
5612 .c_ushort_type,
5613 .c_int_type,
5614 .c_uint_type,
5615 .c_long_type,
5616 .c_ulong_type,
5617 .c_longlong_type,
5618 .c_ulonglong_type,
5619 => .Int,
5620
5621 .c_longdouble_type,
5622 .f16_type,
5623 .f32_type,
5624 .f64_type,
5625 .f80_type,
5626 .f128_type,
5627 => .Float,
5628
5629 .anyopaque_type => .Opaque,
5630 .bool_type => .Bool,
5631 .void_type => .Void,
5632 .type_type => .Type,
5633 .anyerror_type => .ErrorSet,
5634 .comptime_int_type => .ComptimeInt,
5635 .comptime_float_type => .ComptimeFloat,
5636 .noreturn_type => .NoReturn,
5637 .anyframe_type => .AnyFrame,
5638 .null_type => .Null,
5639 .undefined_type => .Undefined,
5640 .enum_literal_type => .EnumLiteral,
5641
5642 .atomic_order_type,
5643 .atomic_rmw_op_type,
5644 .calling_convention_type,
5645 .address_space_type,
5646 .float_mode_type,
5647 .reduce_op_type,
5648 .call_modifier_type,
5649 => .Enum,
5650
5651 .prefetch_options_type,
5652 .export_options_type,
5653 .extern_options_type,
5654 => .Struct,
5655
5656 .type_info_type => .Union,
5657
5658 .manyptr_u8_type,
5659 .manyptr_const_u8_type,
5660 .manyptr_const_u8_sentinel_0_type,
5661 .single_const_pointer_to_comptime_int_type,
5662 .slice_const_u8_type,
5663 .slice_const_u8_sentinel_0_type,
5664 => .Pointer,
5665
5666 .anyerror_void_error_union_type => .ErrorUnion,
5667 .empty_struct_type => .Struct,
5668
5669 .generic_poison_type => return error.GenericPoison,
5670
5671 // values, not types
5672 .undef => unreachable,
5673 .zero => unreachable,
5674 .zero_usize => unreachable,
5675 .zero_u8 => unreachable,
5676 .one => unreachable,
5677 .one_usize => unreachable,
5678 .one_u8 => unreachable,
5679 .four_u8 => unreachable,
5680 .negative_one => unreachable,
5681 .calling_convention_c => unreachable,
5682 .calling_convention_inline => unreachable,
5683 .void_value => unreachable,
5684 .unreachable_value => unreachable,
5685 .null_value => unreachable,
5686 .bool_true => unreachable,
5687 .bool_false => unreachable,
5688 .empty_struct => unreachable,
5689 .generic_poison => unreachable,
5690
5691 .var_args_param_type => unreachable, // special tag
5692
5693 _ => switch (ip.items.items(.tag)[@enumToInt(index)]) {
5694 .type_int_signed,
5695 .type_int_unsigned,
5696 => .Int,
5697
5698 .type_array_big,
5699 .type_array_small,
5700 => .Array,
5701
5702 .type_vector => .Vector,
5703
5704 .type_pointer,
5705 .type_slice,
5706 => .Pointer,
5707
5708 .type_optional => .Optional,
5709 .type_anyframe => .AnyFrame,
5710 .type_error_union => .ErrorUnion,
5711
5712 .type_error_set,
5713 .type_inferred_error_set,
5714 => .ErrorSet,
5715
5716 .type_enum_auto,
5717 .type_enum_explicit,
5718 .type_enum_nonexhaustive,
5719 => .Enum,
5720
5721 .simple_type => unreachable, // handled via Index tag above
5722
5723 .type_opaque => .Opaque,
5724
5725 .type_struct,
5726 .type_struct_ns,
5727 .type_struct_anon,
5728 .type_tuple_anon,
5729 => .Struct,
5730
5731 .type_union_tagged,
5732 .type_union_untagged,
5733 .type_union_safety,
5734 => .Union,
5735
5736 .type_function => .Fn,
5737
5738 // values, not types
5739 .undef,
5740 .runtime_value,
5741 .simple_value,
5742 .ptr_decl,
5743 .ptr_mut_decl,
5744 .ptr_comptime_field,
5745 .ptr_int,
5746 .ptr_eu_payload,
5747 .ptr_opt_payload,
5748 .ptr_elem,
5749 .ptr_field,
5750 .ptr_slice,
5751 .opt_payload,
5752 .opt_null,
5753 .int_u8,
5754 .int_u16,
5755 .int_u32,
5756 .int_i32,
5757 .int_usize,
5758 .int_comptime_int_u32,
5759 .int_comptime_int_i32,
5760 .int_small,
5761 .int_positive,
5762 .int_negative,
5763 .int_lazy_align,
5764 .int_lazy_size,
5765 .error_set_error,
5766 .error_union_error,
5767 .error_union_payload,
5768 .enum_literal,
5769 .enum_tag,
5770 .float_f16,
5771 .float_f32,
5772 .float_f64,
5773 .float_f80,
5774 .float_f128,
5775 .float_c_longdouble_f80,
5776 .float_c_longdouble_f128,
5777 .float_comptime_float,
5778 .variable,
5779 .extern_func,
5780 .func,
5781 .only_possible_value,
5782 .union_value,
5783 .bytes,
5784 .aggregate,
5785 .repeated,
5786 // memoization, not types
5787 .memoized_call,
5788 => unreachable,
5789 },
5790 .none => unreachable, // special tag
5791 };
3165792}
src/Liveness.zig+27-29
......@@ -5,15 +5,17 @@
55//! Some instructions are special, such as:
66//! * Conditional Branches
77//! * Switch Branches
8const Liveness = @This();
98const std = @import("std");
10const trace = @import("tracy.zig").trace;
119const log = std.log.scoped(.liveness);
1210const assert = std.debug.assert;
1311const Allocator = std.mem.Allocator;
14const Air = @import("Air.zig");
1512const Log2Int = std.math.Log2Int;
1613
14const Liveness = @This();
15const trace = @import("tracy.zig").trace;
16const Air = @import("Air.zig");
17const InternPool = @import("InternPool.zig");
18
1719pub const Verify = @import("Liveness/Verify.zig");
1820
1921/// This array is split into sets of 4 bits per AIR instruction.
......@@ -129,7 +131,7 @@ fn LivenessPassData(comptime pass: LivenessPass) type {
129131 };
130132}
131133
132pub fn analyze(gpa: Allocator, air: Air) Allocator.Error!Liveness {
134pub fn analyze(gpa: Allocator, air: Air, intern_pool: *const InternPool) Allocator.Error!Liveness {
133135 const tracy = trace(@src());
134136 defer tracy.end();
135137
......@@ -142,6 +144,7 @@ pub fn analyze(gpa: Allocator, air: Air) Allocator.Error!Liveness {
142144 ),
143145 .extra = .{},
144146 .special = .{},
147 .intern_pool = intern_pool,
145148 };
146149 errdefer gpa.free(a.tomb_bits);
147150 errdefer a.special.deinit(gpa);
......@@ -222,6 +225,7 @@ pub fn categorizeOperand(
222225 air: Air,
223226 inst: Air.Inst.Index,
224227 operand: Air.Inst.Index,
228 ip: *const InternPool,
225229) OperandCategory {
226230 const air_tags = air.instructions.items(.tag);
227231 const air_datas = air.instructions.items(.data);
......@@ -317,9 +321,10 @@ pub fn categorizeOperand(
317321
318322 .arg,
319323 .alloc,
324 .inferred_alloc,
325 .inferred_alloc_comptime,
320326 .ret_ptr,
321 .constant,
322 .const_ty,
327 .interned,
323328 .trap,
324329 .breakpoint,
325330 .dbg_stmt,
......@@ -530,7 +535,7 @@ pub fn categorizeOperand(
530535 .aggregate_init => {
531536 const ty_pl = air_datas[inst].ty_pl;
532537 const aggregate_ty = air.getRefType(ty_pl.ty);
533 const len = @intCast(usize, aggregate_ty.arrayLen());
538 const len = @intCast(usize, aggregate_ty.arrayLenIp(ip));
534539 const elements = @ptrCast([]const Air.Inst.Ref, air.extra[ty_pl.payload..][0..len]);
535540
536541 if (elements.len <= bpi - 1) {
......@@ -621,7 +626,7 @@ pub fn categorizeOperand(
621626
622627 var operand_live: bool = true;
623628 for (air.extra[cond_extra.end..][0..2]) |cond_inst| {
624 if (l.categorizeOperand(air, cond_inst, operand) == .tomb)
629 if (l.categorizeOperand(air, cond_inst, operand, ip) == .tomb)
625630 operand_live = false;
626631
627632 switch (air_tags[cond_inst]) {
......@@ -818,6 +823,7 @@ pub const BigTomb = struct {
818823const Analysis = struct {
819824 gpa: Allocator,
820825 air: Air,
826 intern_pool: *const InternPool,
821827 tomb_bits: []usize,
822828 special: std.AutoHashMapUnmanaged(Air.Inst.Index, u32),
823829 extra: std.ArrayListUnmanaged(u32),
......@@ -867,6 +873,7 @@ fn analyzeInst(
867873 data: *LivenessPassData(pass),
868874 inst: Air.Inst.Index,
869875) Allocator.Error!void {
876 const ip = a.intern_pool;
870877 const inst_tags = a.air.instructions.items(.tag);
871878 const inst_datas = a.air.instructions.items(.data);
872879
......@@ -967,9 +974,7 @@ fn analyzeInst(
967974 .work_group_id,
968975 => return analyzeOperands(a, pass, data, inst, .{ .none, .none, .none }),
969976
970 .constant,
971 .const_ty,
972 => unreachable,
977 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
973978
974979 .trap,
975980 .unreach,
......@@ -1134,7 +1139,7 @@ fn analyzeInst(
11341139 .aggregate_init => {
11351140 const ty_pl = inst_datas[inst].ty_pl;
11361141 const aggregate_ty = a.air.getRefType(ty_pl.ty);
1137 const len = @intCast(usize, aggregate_ty.arrayLen());
1142 const len = @intCast(usize, aggregate_ty.arrayLenIp(ip));
11381143 const elements = @ptrCast([]const Air.Inst.Ref, a.air.extra[ty_pl.payload..][0..len]);
11391144
11401145 if (elements.len <= bpi - 1) {
......@@ -1253,19 +1258,17 @@ fn analyzeOperands(
12531258) Allocator.Error!void {
12541259 const gpa = a.gpa;
12551260 const inst_tags = a.air.instructions.items(.tag);
1261 const ip = a.intern_pool;
12561262
12571263 switch (pass) {
12581264 .loop_analysis => {
12591265 _ = data.live_set.remove(inst);
12601266
12611267 for (operands) |op_ref| {
1262 const operand = Air.refToIndex(op_ref) orelse continue;
1268 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
12631269
12641270 // Don't compute any liveness for constants
1265 switch (inst_tags[operand]) {
1266 .constant, .const_ty => continue,
1267 else => {},
1268 }
1271 if (inst_tags[operand] == .interned) continue;
12691272
12701273 _ = try data.live_set.put(gpa, operand, {});
12711274 }
......@@ -1288,20 +1291,17 @@ fn analyzeOperands(
12881291 // If our result is unused and the instruction doesn't need to be lowered, backends will
12891292 // skip the lowering of this instruction, so we don't want to record uses of operands.
12901293 // That way, we can mark as many instructions as possible unused.
1291 if (!immediate_death or a.air.mustLower(inst)) {
1294 if (!immediate_death or a.air.mustLower(inst, ip)) {
12921295 // Note that it's important we iterate over the operands backwards, so that if a dying
12931296 // operand is used multiple times we mark its last use as its death.
12941297 var i = operands.len;
12951298 while (i > 0) {
12961299 i -= 1;
12971300 const op_ref = operands[i];
1298 const operand = Air.refToIndex(op_ref) orelse continue;
1301 const operand = Air.refToIndexAllowNone(op_ref) orelse continue;
12991302
13001303 // Don't compute any liveness for constants
1301 switch (inst_tags[operand]) {
1302 .constant, .const_ty => continue,
1303 else => {},
1304 }
1304 if (inst_tags[operand] == .interned) continue;
13051305
13061306 const mask = @as(Bpi, 1) << @intCast(OperandInt, i);
13071307
......@@ -1407,7 +1407,7 @@ fn analyzeInstBlock(
14071407
14081408 // If the block is noreturn, block deaths not only aren't useful, they're impossible to
14091409 // find: there could be more stuff alive after the block than before it!
1410 if (!a.air.getRefType(ty_pl.ty).isNoReturn()) {
1410 if (!a.intern_pool.isNoReturn(a.air.getRefType(ty_pl.ty).ip_index)) {
14111411 // The block kills the difference in the live sets
14121412 const block_scope = data.block_scopes.get(inst).?;
14131413 const num_deaths = data.live_set.count() - block_scope.live_set.count();
......@@ -1819,6 +1819,7 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
18191819
18201820 /// Must be called with operands in reverse order.
18211821 fn feed(big: *Self, op_ref: Air.Inst.Ref) !void {
1822 const ip = big.a.intern_pool;
18221823 // Note that after this, `operands_remaining` becomes the index of the current operand
18231824 big.operands_remaining -= 1;
18241825
......@@ -1831,15 +1832,12 @@ fn AnalyzeBigOperands(comptime pass: LivenessPass) type {
18311832
18321833 // Don't compute any liveness for constants
18331834 const inst_tags = big.a.air.instructions.items(.tag);
1834 switch (inst_tags[operand]) {
1835 .constant, .const_ty => return,
1836 else => {},
1837 }
1835 if (inst_tags[operand] == .interned) return
18381836
18391837 // If our result is unused and the instruction doesn't need to be lowered, backends will
18401838 // skip the lowering of this instruction, so we don't want to record uses of operands.
18411839 // That way, we can mark as many instructions as possible unused.
1842 if (big.will_die_immediately and !big.a.air.mustLower(big.inst)) return;
1840 if (big.will_die_immediately and !big.a.air.mustLower(big.inst, ip)) return;
18431841
18441842 const extra_byte = (big.operands_remaining - (bpi - 1)) / 31;
18451843 const extra_bit = @intCast(u5, big.operands_remaining - (bpi - 1) - extra_byte * 31);
src/Liveness/Verify.zig+62-57
......@@ -5,6 +5,7 @@ air: Air,
55liveness: Liveness,
66live: LiveMap = .{},
77blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, LiveMap) = .{},
8intern_pool: *const InternPool,
89
910pub const Error = error{ LivenessInvalid, OutOfMemory };
1011
......@@ -27,10 +28,11 @@ pub fn verify(self: *Verify) Error!void {
2728const LiveMap = std.AutoHashMapUnmanaged(Air.Inst.Index, void);
2829
2930fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
31 const ip = self.intern_pool;
3032 const tag = self.air.instructions.items(.tag);
3133 const data = self.air.instructions.items(.data);
3234 for (body) |inst| {
33 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
35 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) {
3436 // This instruction will not be lowered and should be ignored.
3537 continue;
3638 }
......@@ -39,9 +41,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
3941 // no operands
4042 .arg,
4143 .alloc,
44 .inferred_alloc,
45 .inferred_alloc_comptime,
4246 .ret_ptr,
43 .constant,
44 .const_ty,
47 .interned,
4548 .breakpoint,
4649 .dbg_stmt,
4750 .dbg_inline_begin,
......@@ -58,10 +61,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
5861 .work_item_id,
5962 .work_group_size,
6063 .work_group_id,
61 => try self.verifyInst(inst, .{ .none, .none, .none }),
64 => try self.verifyInstOperands(inst, .{ .none, .none, .none }),
6265
6366 .trap, .unreach => {
64 try self.verifyInst(inst, .{ .none, .none, .none });
67 try self.verifyInstOperands(inst, .{ .none, .none, .none });
6568 // This instruction terminates the function, so everything should be dead
6669 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
6770 },
......@@ -110,7 +113,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
110113 .c_va_copy,
111114 => {
112115 const ty_op = data[inst].ty_op;
113 try self.verifyInst(inst, .{ ty_op.operand, .none, .none });
116 try self.verifyInstOperands(inst, .{ ty_op.operand, .none, .none });
114117 },
115118 .is_null,
116119 .is_non_null,
......@@ -146,13 +149,13 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
146149 .c_va_end,
147150 => {
148151 const un_op = data[inst].un_op;
149 try self.verifyInst(inst, .{ un_op, .none, .none });
152 try self.verifyInstOperands(inst, .{ un_op, .none, .none });
150153 },
151154 .ret,
152155 .ret_load,
153156 => {
154157 const un_op = data[inst].un_op;
155 try self.verifyInst(inst, .{ un_op, .none, .none });
158 try self.verifyInstOperands(inst, .{ un_op, .none, .none });
156159 // This instruction terminates the function, so everything should be dead
157160 if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst});
158161 },
......@@ -161,36 +164,36 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
161164 .wasm_memory_grow,
162165 => {
163166 const pl_op = data[inst].pl_op;
164 try self.verifyInst(inst, .{ pl_op.operand, .none, .none });
167 try self.verifyInstOperands(inst, .{ pl_op.operand, .none, .none });
165168 },
166169 .prefetch => {
167170 const prefetch = data[inst].prefetch;
168 try self.verifyInst(inst, .{ prefetch.ptr, .none, .none });
171 try self.verifyInstOperands(inst, .{ prefetch.ptr, .none, .none });
169172 },
170173 .reduce,
171174 .reduce_optimized,
172175 => {
173176 const reduce = data[inst].reduce;
174 try self.verifyInst(inst, .{ reduce.operand, .none, .none });
177 try self.verifyInstOperands(inst, .{ reduce.operand, .none, .none });
175178 },
176179 .union_init => {
177180 const ty_pl = data[inst].ty_pl;
178181 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
179 try self.verifyInst(inst, .{ extra.init, .none, .none });
182 try self.verifyInstOperands(inst, .{ extra.init, .none, .none });
180183 },
181184 .struct_field_ptr, .struct_field_val => {
182185 const ty_pl = data[inst].ty_pl;
183186 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
184 try self.verifyInst(inst, .{ extra.struct_operand, .none, .none });
187 try self.verifyInstOperands(inst, .{ extra.struct_operand, .none, .none });
185188 },
186189 .field_parent_ptr => {
187190 const ty_pl = data[inst].ty_pl;
188191 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
189 try self.verifyInst(inst, .{ extra.field_ptr, .none, .none });
192 try self.verifyInstOperands(inst, .{ extra.field_ptr, .none, .none });
190193 },
191194 .atomic_load => {
192195 const atomic_load = data[inst].atomic_load;
193 try self.verifyInst(inst, .{ atomic_load.ptr, .none, .none });
196 try self.verifyInstOperands(inst, .{ atomic_load.ptr, .none, .none });
194197 },
195198
196199 // binary
......@@ -260,7 +263,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
260263 .memcpy,
261264 => {
262265 const bin_op = data[inst].bin_op;
263 try self.verifyInst(inst, .{ bin_op.lhs, bin_op.rhs, .none });
266 try self.verifyInstOperands(inst, .{ bin_op.lhs, bin_op.rhs, .none });
264267 },
265268 .add_with_overflow,
266269 .sub_with_overflow,
......@@ -274,62 +277,62 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
274277 => {
275278 const ty_pl = data[inst].ty_pl;
276279 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
277 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none });
280 try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, .none });
278281 },
279282 .shuffle => {
280283 const ty_pl = data[inst].ty_pl;
281284 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
282 try self.verifyInst(inst, .{ extra.a, extra.b, .none });
285 try self.verifyInstOperands(inst, .{ extra.a, extra.b, .none });
283286 },
284287 .cmp_vector,
285288 .cmp_vector_optimized,
286289 => {
287290 const ty_pl = data[inst].ty_pl;
288291 const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data;
289 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none });
292 try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, .none });
290293 },
291294 .atomic_rmw => {
292295 const pl_op = data[inst].pl_op;
293296 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;
294 try self.verifyInst(inst, .{ pl_op.operand, extra.operand, .none });
297 try self.verifyInstOperands(inst, .{ pl_op.operand, extra.operand, .none });
295298 },
296299
297300 // ternary
298301 .select => {
299302 const pl_op = data[inst].pl_op;
300303 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
301 try self.verifyInst(inst, .{ pl_op.operand, extra.lhs, extra.rhs });
304 try self.verifyInstOperands(inst, .{ pl_op.operand, extra.lhs, extra.rhs });
302305 },
303306 .mul_add => {
304307 const pl_op = data[inst].pl_op;
305308 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
306 try self.verifyInst(inst, .{ extra.lhs, extra.rhs, pl_op.operand });
309 try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, pl_op.operand });
307310 },
308311 .vector_store_elem => {
309312 const vector_store_elem = data[inst].vector_store_elem;
310313 const extra = self.air.extraData(Air.Bin, vector_store_elem.payload).data;
311 try self.verifyInst(inst, .{ vector_store_elem.vector_ptr, extra.lhs, extra.rhs });
314 try self.verifyInstOperands(inst, .{ vector_store_elem.vector_ptr, extra.lhs, extra.rhs });
312315 },
313316 .cmpxchg_strong,
314317 .cmpxchg_weak,
315318 => {
316319 const ty_pl = data[inst].ty_pl;
317320 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
318 try self.verifyInst(inst, .{ extra.ptr, extra.expected_value, extra.new_value });
321 try self.verifyInstOperands(inst, .{ extra.ptr, extra.expected_value, extra.new_value });
319322 },
320323
321324 // big tombs
322325 .aggregate_init => {
323326 const ty_pl = data[inst].ty_pl;
324327 const aggregate_ty = self.air.getRefType(ty_pl.ty);
325 const len = @intCast(usize, aggregate_ty.arrayLen());
328 const len = @intCast(usize, aggregate_ty.arrayLenIp(ip));
326329 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
327330
328331 var bt = self.liveness.iterateBigTomb(inst);
329332 for (elements) |element| {
330333 try self.verifyOperand(inst, element, bt.feed());
331334 }
332 try self.verifyInst(inst, .{ .none, .none, .none });
335 try self.verifyInst(inst);
333336 },
334337 .call, .call_always_tail, .call_never_tail, .call_never_inline => {
335338 const pl_op = data[inst].pl_op;
......@@ -344,7 +347,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
344347 for (args) |arg| {
345348 try self.verifyOperand(inst, arg, bt.feed());
346349 }
347 try self.verifyInst(inst, .{ .none, .none, .none });
350 try self.verifyInst(inst);
348351 },
349352 .assembly => {
350353 const ty_pl = data[inst].ty_pl;
......@@ -370,7 +373,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
370373 for (inputs) |input| {
371374 try self.verifyOperand(inst, input, bt.feed());
372375 }
373 try self.verifyInst(inst, .{ .none, .none, .none });
376 try self.verifyInst(inst);
374377 },
375378
376379 // control flow
......@@ -394,7 +397,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
394397
395398 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);
396399
397 try self.verifyInst(inst, .{ .none, .none, .none });
400 try self.verifyInst(inst);
398401 },
399402 .try_ptr => {
400403 const ty_pl = data[inst].ty_pl;
......@@ -416,7 +419,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
416419
417420 for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death);
418421
419 try self.verifyInst(inst, .{ .none, .none, .none });
422 try self.verifyInst(inst);
420423 },
421424 .br => {
422425 const br = data[inst].br;
......@@ -428,7 +431,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
428431 } else {
429432 gop.value_ptr.* = try self.live.clone(self.gpa);
430433 }
431 try self.verifyInst(inst, .{ .none, .none, .none });
434 try self.verifyInst(inst);
432435 },
433436 .block => {
434437 const ty_pl = data[inst].ty_pl;
......@@ -450,7 +453,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
450453
451454 for (block_liveness.deaths) |death| try self.verifyDeath(inst, death);
452455
453 if (block_ty.isNoReturn()) {
456 if (ip.isNoReturn(block_ty.toIntern())) {
454457 assert(!self.blocks.contains(inst));
455458 } else {
456459 var live = self.blocks.fetchRemove(inst).?.value;
......@@ -459,7 +462,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
459462 try self.verifyMatchingLiveness(inst, live);
460463 }
461464
462 try self.verifyInst(inst, .{ .none, .none, .none });
465 try self.verifyInstOperands(inst, .{ .none, .none, .none });
463466 },
464467 .loop => {
465468 const ty_pl = data[inst].ty_pl;
......@@ -474,7 +477,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
474477 // The same stuff should be alive after the loop as before it
475478 try self.verifyMatchingLiveness(inst, live);
476479
477 try self.verifyInst(inst, .{ .none, .none, .none });
480 try self.verifyInstOperands(inst, .{ .none, .none, .none });
478481 },
479482 .cond_br => {
480483 const pl_op = data[inst].pl_op;
......@@ -497,7 +500,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
497500 for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death);
498501 try self.verifyBody(else_body);
499502
500 try self.verifyInst(inst, .{ .none, .none, .none });
503 try self.verifyInst(inst);
501504 },
502505 .switch_br => {
503506 const pl_op = data[inst].pl_op;
......@@ -541,7 +544,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
541544 try self.verifyBody(else_body);
542545 }
543546
544 try self.verifyInst(inst, .{ .none, .none, .none });
547 try self.verifyInst(inst);
545548 },
546549 }
547550 }
......@@ -552,20 +555,22 @@ fn verifyDeath(self: *Verify, inst: Air.Inst.Index, operand: Air.Inst.Index) Err
552555}
553556
554557fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies: bool) Error!void {
555 const operand = Air.refToIndex(op_ref) orelse return;
556 switch (self.air.instructions.items(.tag)[operand]) {
557 .constant, .const_ty => {},
558 else => {
559 if (dies) {
560 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });
561 } else {
562 if (!self.live.contains(operand)) return invalid("%{}: dead operand %{} reused", .{ inst, operand });
563 }
564 },
558 const operand = Air.refToIndexAllowNone(op_ref) orelse {
559 assert(!dies);
560 return;
561 };
562 if (self.air.instructions.items(.tag)[operand] == .interned) {
563 assert(!dies);
564 return;
565 }
566 if (dies) {
567 if (!self.live.remove(operand)) return invalid("%{}: dead operand %{} reused and killed again", .{ inst, operand });
568 } else {
569 if (!self.live.contains(operand)) return invalid("%{}: dead operand %{} reused", .{ inst, operand });
565570 }
566571}
567572
568fn verifyInst(
573fn verifyInstOperands(
569574 self: *Verify,
570575 inst: Air.Inst.Index,
571576 operands: [Liveness.bpi - 1]Air.Inst.Ref,
......@@ -574,16 +579,15 @@ fn verifyInst(
574579 const dies = self.liveness.operandDies(inst, @intCast(Liveness.OperandInt, operand_index));
575580 try self.verifyOperand(inst, operand, dies);
576581 }
577 const tag = self.air.instructions.items(.tag);
578 switch (tag[inst]) {
579 .constant, .const_ty => unreachable,
580 else => {
581 if (self.liveness.isUnused(inst)) {
582 assert(!self.live.contains(inst));
583 } else {
584 try self.live.putNoClobber(self.gpa, inst, {});
585 }
586 },
582 try self.verifyInst(inst);
583}
584
585fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void {
586 if (self.air.instructions.items(.tag)[inst] == .interned) return;
587 if (self.liveness.isUnused(inst)) {
588 assert(!self.live.contains(inst));
589 } else {
590 try self.live.putNoClobber(self.gpa, inst, {});
587591 }
588592}
589593
......@@ -604,4 +608,5 @@ const log = std.log.scoped(.liveness_verify);
604608
605609const Air = @import("../Air.zig");
606610const Liveness = @import("../Liveness.zig");
611const InternPool = @import("../InternPool.zig");
607612const Verify = @This();
src/Module.zig+1440-1086
......@@ -32,6 +32,19 @@ const build_options = @import("build_options");
3232const Liveness = @import("Liveness.zig");
3333const isUpDir = @import("introspect.zig").isUpDir;
3434const clang = @import("clang.zig");
35const InternPool = @import("InternPool.zig");
36
37comptime {
38 @setEvalBranchQuota(4000);
39 for (
40 @typeInfo(Zir.Inst.Ref).Enum.fields,
41 @typeInfo(Air.Inst.Ref).Enum.fields,
42 @typeInfo(InternPool.Index).Enum.fields,
43 ) |zir_field, air_field, ip_field| {
44 assert(mem.eql(u8, zir_field.name, ip_field.name));
45 assert(mem.eql(u8, air_field.name, ip_field.name));
46 }
47}
3548
3649/// General-purpose allocator. Used for both temporary and long-term storage.
3750gpa: Allocator,
......@@ -72,28 +85,29 @@ import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
7285/// Keys are fully resolved file paths. This table owns the keys and values.
7386embed_table: std.StringHashMapUnmanaged(*EmbedFile) = .{},
7487
75/// This is a temporary addition to stage2 in order to match legacy behavior,
76/// however the end-game once the lang spec is settled will be to use a global
77/// InternPool for comptime memoized objects, making this behavior consistent across all types,
78/// not only string literals. Or, we might decide to not guarantee string literals
79/// to have equal comptime pointers, in which case this field can be deleted (perhaps
80/// the commit that introduced it can simply be reverted).
81/// This table uses an optional index so that when a Decl is destroyed, the string literal
82/// is still reclaimable by a future Decl.
83string_literal_table: std.HashMapUnmanaged(StringLiteralContext.Key, Decl.OptionalIndex, StringLiteralContext, std.hash_map.default_max_load_percentage) = .{},
84string_literal_bytes: ArrayListUnmanaged(u8) = .{},
88/// Stores all Type and Value objects; periodically garbage collected.
89intern_pool: InternPool = .{},
8590
91/// To be eliminated in a future commit by moving more data into InternPool.
92/// Current uses that must be eliminated:
93/// * Struct comptime_args
94/// * Struct optimized_order
95/// * Union fields
96/// This memory lives until the Module is destroyed.
97tmp_hack_arena: std.heap.ArenaAllocator,
98
99/// This is currently only used for string literals.
100memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
101
102monomorphed_func_keys: std.ArrayListUnmanaged(InternPool.Index) = .{},
86103/// The set of all the generic function instantiations. This is used so that when a generic
87104/// function is called twice with the same comptime parameter arguments, both calls dispatch
88105/// to the same function.
89106monomorphed_funcs: MonomorphedFuncsSet = .{},
90/// The set of all comptime function calls that have been cached so that future calls
91/// with the same parameters will get the same return value.
92memoized_calls: MemoizedCallSet = .{},
93107/// Contains the values from `@setAlignStack`. A sparse table is used here
94108/// instead of a field of `Fn` because usage of `@setAlignStack` is rare, while
95109/// functions are many.
96align_stack_fns: std.AutoHashMapUnmanaged(*const Fn, SetAlignStack) = .{},
110align_stack_fns: std.AutoHashMapUnmanaged(Fn.Index, SetAlignStack) = .{},
97111
98112/// We optimize memory usage for a compilation with no compile errors by storing the
99113/// error messages and mapping outside of `Decl`.
......@@ -120,13 +134,8 @@ cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, []CImportError) = .{},
120134/// contains Decls that need to be deleted if they end up having no references to them.
121135deletion_set: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .{},
122136
123/// Error tags and their values, tag names are duped with mod.gpa.
124/// Corresponds with `error_name_list`.
125global_error_set: std.StringHashMapUnmanaged(ErrorInt) = .{},
126
127/// ErrorInt -> []const u8 for fast lookups for @intToError at comptime
128/// Corresponds with `global_error_set`.
129error_name_list: ArrayListUnmanaged([]const u8),
137/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
138global_error_set: GlobalErrorSet = .{},
130139
131140/// Incrementing integer used to compare against the corresponding Decl
132141/// field to determine whether a Decl's status applies to an ongoing update, or a
......@@ -165,6 +174,11 @@ allocated_decls: std.SegmentedList(Decl, 0) = .{},
165174/// When a Decl object is freed from `allocated_decls`, it is pushed into this stack.
166175decls_free_list: ArrayListUnmanaged(Decl.Index) = .{},
167176
177/// Same pattern as with `allocated_decls`.
178allocated_namespaces: std.SegmentedList(Namespace, 0) = .{},
179/// Same pattern as with `decls_free_list`.
180namespaces_free_list: ArrayListUnmanaged(Namespace.Index) = .{},
181
168182global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
169183
170184reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
......@@ -172,6 +186,8 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
172186 src: LazySrcLoc,
173187}) = .{},
174188
189pub const GlobalErrorSet = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
190
175191pub const CImportError = struct {
176192 offset: u32,
177193 line: u32,
......@@ -187,108 +203,40 @@ pub const CImportError = struct {
187203 }
188204};
189205
190pub const StringLiteralContext = struct {
191 bytes: *ArrayListUnmanaged(u8),
192
193 pub const Key = struct {
194 index: u32,
195 len: u32,
196 };
197
198 pub fn eql(self: @This(), a: Key, b: Key) bool {
199 _ = self;
200 return a.index == b.index and a.len == b.len;
201 }
202
203 pub fn hash(self: @This(), x: Key) u64 {
204 const x_slice = self.bytes.items[x.index..][0..x.len];
205 return std.hash_map.hashString(x_slice);
206 }
207};
208
209pub const StringLiteralAdapter = struct {
210 bytes: *ArrayListUnmanaged(u8),
206pub const MonomorphedFuncKey = struct { func: Fn.Index, args_index: u32, args_len: u32 };
211207
212 pub fn eql(self: @This(), a_slice: []const u8, b: StringLiteralContext.Key) bool {
213 const b_slice = self.bytes.items[b.index..][0..b.len];
214 return mem.eql(u8, a_slice, b_slice);
215 }
208pub const MonomorphedFuncAdaptedKey = struct { func: Fn.Index, args: []const InternPool.Index };
216209
217 pub fn hash(self: @This(), adapted_key: []const u8) u64 {
218 _ = self;
219 return std.hash_map.hashString(adapted_key);
220 }
221};
222
223const MonomorphedFuncsSet = std.HashMapUnmanaged(
224 *Fn,
225 void,
210pub const MonomorphedFuncsSet = std.HashMapUnmanaged(
211 MonomorphedFuncKey,
212 InternPool.Index,
226213 MonomorphedFuncsContext,
227214 std.hash_map.default_max_load_percentage,
228215);
229216
230const MonomorphedFuncsContext = struct {
231 pub fn eql(ctx: @This(), a: *Fn, b: *Fn) bool {
232 _ = ctx;
233 return a == b;
217pub const MonomorphedFuncsContext = struct {
218 mod: *Module,
219
220 pub fn eql(_: @This(), a: MonomorphedFuncKey, b: MonomorphedFuncKey) bool {
221 return std.meta.eql(a, b);
234222 }
235223
236 /// Must match `Sema.GenericCallAdapter.hash`.
237 pub fn hash(ctx: @This(), key: *Fn) u64 {
238 _ = ctx;
239 return key.hash;
224 pub fn hash(ctx: @This(), key: MonomorphedFuncKey) u64 {
225 const key_args = ctx.mod.monomorphed_func_keys.items[key.args_index..][0..key.args_len];
226 return std.hash.Wyhash.hash(@enumToInt(key.func), std.mem.sliceAsBytes(key_args));
240227 }
241228};
242229
243pub const MemoizedCallSet = std.HashMapUnmanaged(
244 MemoizedCall.Key,
245 MemoizedCall.Result,
246 MemoizedCall,
247 std.hash_map.default_max_load_percentage,
248);
249
250pub const MemoizedCall = struct {
251 module: *Module,
252
253 pub const Key = struct {
254 func: *Fn,
255 args: []TypedValue,
256 };
257
258 pub const Result = struct {
259 val: Value,
260 arena: std.heap.ArenaAllocator.State,
261 };
262
263 pub fn eql(ctx: @This(), a: Key, b: Key) bool {
264 if (a.func != b.func) return false;
265
266 assert(a.args.len == b.args.len);
267 for (a.args, 0..) |a_arg, arg_i| {
268 const b_arg = b.args[arg_i];
269 if (!a_arg.eql(b_arg, ctx.module)) {
270 return false;
271 }
272 }
230pub const MonomorphedFuncsAdaptedContext = struct {
231 mod: *Module,
273232
274 return true;
233 pub fn eql(ctx: @This(), adapted_key: MonomorphedFuncAdaptedKey, other_key: MonomorphedFuncKey) bool {
234 const other_key_args = ctx.mod.monomorphed_func_keys.items[other_key.args_index..][0..other_key.args_len];
235 return adapted_key.func == other_key.func and std.mem.eql(InternPool.Index, adapted_key.args, other_key_args);
275236 }
276237
277 /// Must match `Sema.GenericCallAdapter.hash`.
278 pub fn hash(ctx: @This(), key: Key) u64 {
279 var hasher = std.hash.Wyhash.init(0);
280
281 // The generic function Decl is guaranteed to be the first dependency
282 // of each of its instantiations.
283 std.hash.autoHash(&hasher, key.func);
284
285 // This logic must be kept in sync with the logic in `analyzeCall` that
286 // computes the hash.
287 for (key.args) |arg| {
288 arg.hash(&hasher, ctx.module);
289 }
290
291 return hasher.final();
238 pub fn hash(_: @This(), adapted_key: MonomorphedFuncAdaptedKey) u64 {
239 return std.hash.Wyhash.hash(@enumToInt(adapted_key.func), std.mem.sliceAsBytes(adapted_key.args));
292240 }
293241};
294242
......@@ -322,7 +270,7 @@ pub const GlobalEmitH = struct {
322270pub const ErrorInt = u32;
323271
324272pub const Export = struct {
325 options: std.builtin.ExportOptions,
273 opts: Options,
326274 src: LazySrcLoc,
327275 /// The Decl that performs the export. Note that this is *not* the Decl being exported.
328276 owner_decl: Decl.Index,
......@@ -340,10 +288,17 @@ pub const Export = struct {
340288 complete,
341289 },
342290
291 pub const Options = struct {
292 name: InternPool.NullTerminatedString,
293 linkage: std.builtin.GlobalLinkage = .Strong,
294 section: InternPool.OptionalNullTerminatedString = .none,
295 visibility: std.builtin.SymbolVisibility = .default,
296 };
297
343298 pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc {
344299 const src_decl = mod.declPtr(exp.src_decl);
345300 return .{
346 .file_scope = src_decl.getFileScope(),
301 .file_scope = src_decl.getFileScope(mod),
347302 .parent_decl_node = src_decl.src_node,
348303 .lazy = exp.src,
349304 };
......@@ -351,61 +306,76 @@ pub const Export = struct {
351306};
352307
353308pub const CaptureScope = struct {
309 refs: u32,
354310 parent: ?*CaptureScope,
355311
356312 /// Values from this decl's evaluation that will be closed over in
357 /// child decls. Values stored in the value_arena of the linked decl.
358 /// During sema, this map is backed by the gpa. Once sema completes,
359 /// it is reallocated using the value_arena.
360 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, TypedValue) = .{},
313 /// child decls. This map is backed by the gpa, and deinited when
314 /// the refcount reaches 0.
315 captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Capture) = .{},
361316
362 pub fn failed(noalias self: *const @This()) bool {
317 pub const Capture = union(enum) {
318 comptime_val: InternPool.Index, // index of value
319 runtime_val: InternPool.Index, // index of type
320 };
321
322 pub fn failed(noalias self: *const CaptureScope) bool {
363323 return self.captures.available == 0 and self.captures.size == std.math.maxInt(u32);
364324 }
365325
366 pub fn fail(noalias self: *@This()) void {
326 pub fn fail(noalias self: *CaptureScope, gpa: Allocator) void {
327 self.captures.deinit(gpa);
367328 self.captures.available = 0;
368329 self.captures.size = std.math.maxInt(u32);
369330 }
331
332 pub fn incRef(self: *CaptureScope) void {
333 self.refs += 1;
334 }
335
336 pub fn decRef(self: *CaptureScope, gpa: Allocator) void {
337 self.refs -= 1;
338 if (self.refs > 0) return;
339 if (self.parent) |p| p.decRef(gpa);
340 if (!self.failed()) {
341 self.captures.deinit(gpa);
342 }
343 gpa.destroy(self);
344 }
370345};
371346
372347pub const WipCaptureScope = struct {
373348 scope: *CaptureScope,
374349 finalized: bool,
375350 gpa: Allocator,
376 perm_arena: Allocator,
377351
378 pub fn init(gpa: Allocator, perm_arena: Allocator, parent: ?*CaptureScope) !@This() {
379 const scope = try perm_arena.create(CaptureScope);
380 scope.* = .{ .parent = parent };
381 return @This(){
352 pub fn init(gpa: Allocator, parent: ?*CaptureScope) !WipCaptureScope {
353 const scope = try gpa.create(CaptureScope);
354 if (parent) |p| p.incRef();
355 scope.* = .{ .refs = 1, .parent = parent };
356 return .{
382357 .scope = scope,
383358 .finalized = false,
384359 .gpa = gpa,
385 .perm_arena = perm_arena,
386360 };
387361 }
388362
389 pub fn finalize(noalias self: *@This()) !void {
390 assert(!self.finalized);
391 // use a temp to avoid unintentional aliasing due to RLS
392 const tmp = try self.scope.captures.clone(self.perm_arena);
393 self.scope.captures.deinit(self.gpa);
394 self.scope.captures = tmp;
363 pub fn finalize(noalias self: *WipCaptureScope) !void {
395364 self.finalized = true;
396365 }
397366
398 pub fn reset(noalias self: *@This(), parent: ?*CaptureScope) !void {
399 if (!self.finalized) try self.finalize();
400 self.scope = try self.perm_arena.create(CaptureScope);
401 self.scope.* = .{ .parent = parent };
402 self.finalized = false;
367 pub fn reset(noalias self: *WipCaptureScope, parent: ?*CaptureScope) !void {
368 self.scope.decRef(self.gpa);
369 self.scope = try self.gpa.create(CaptureScope);
370 if (parent) |p| p.incRef();
371 self.scope.* = .{ .refs = 1, .parent = parent };
403372 }
404373
405 pub fn deinit(noalias self: *@This()) void {
406 if (!self.finalized) {
407 self.scope.captures.deinit(self.gpa);
408 self.scope.fail();
374 pub fn deinit(noalias self: *WipCaptureScope) void {
375 if (self.finalized) {
376 self.scope.decRef(self.gpa);
377 } else {
378 self.scope.fail(self.gpa);
409379 }
410380 self.* = undefined;
411381 }
......@@ -452,8 +422,7 @@ const ValueArena = struct {
452422};
453423
454424pub const Decl = struct {
455 /// Allocated with Module's allocator; outlives the ZIR code.
456 name: [*:0]const u8,
425 name: InternPool.NullTerminatedString,
457426 /// The most recent Type of the Decl after a successful semantic analysis.
458427 /// Populated when `has_tv`.
459428 ty: Type,
......@@ -461,20 +430,16 @@ pub const Decl = struct {
461430 /// Populated when `has_tv`.
462431 val: Value,
463432 /// Populated when `has_tv`.
464 /// Points to memory inside value_arena.
465 @"linksection": ?[*:0]const u8,
433 @"linksection": InternPool.OptionalNullTerminatedString,
466434 /// Populated when `has_tv`.
467435 @"align": u32,
468436 /// Populated when `has_tv`.
469437 @"addrspace": std.builtin.AddressSpace,
470 /// The memory for ty, val, align, linksection, and captures.
471 /// If this is `null` then there is no memory management needed.
472 value_arena: ?*ValueArena = null,
473438 /// The direct parent namespace of the Decl.
474439 /// Reference to externally owned memory.
475440 /// In the case of the Decl corresponding to a file, this is
476441 /// the namespace of the struct, since there is no parent.
477 src_namespace: *Namespace,
442 src_namespace: Namespace.Index,
478443
479444 /// The scope which lexically contains this decl. A decl must depend
480445 /// on its lexical parent, in order to ensure that this pointer is valid.
......@@ -624,55 +589,17 @@ pub const Decl = struct {
624589 function_body,
625590 };
626591
627 pub fn clearName(decl: *Decl, gpa: Allocator) void {
628 gpa.free(mem.sliceTo(decl.name, 0));
629 decl.name = undefined;
630 }
631
632592 pub fn clearValues(decl: *Decl, mod: *Module) void {
633 const gpa = mod.gpa;
634 if (decl.getExternFn()) |extern_fn| {
635 extern_fn.deinit(gpa);
636 gpa.destroy(extern_fn);
637 }
638 if (decl.getFunction()) |func| {
593 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
639594 _ = mod.align_stack_fns.remove(func);
640 if (func.comptime_args != null) {
641 _ = mod.monomorphed_funcs.remove(func);
642 }
643 func.deinit(gpa);
644 gpa.destroy(func);
645 }
646 if (decl.getVariable()) |variable| {
647 variable.deinit(gpa);
648 gpa.destroy(variable);
649 }
650 if (decl.value_arena) |value_arena| {
651 if (decl.owns_tv) {
652 if (decl.val.castTag(.str_lit)) |str_lit| {
653 mod.string_literal_table.getPtrContext(str_lit.data, .{
654 .bytes = &mod.string_literal_bytes,
655 }).?.* = .none;
656 }
657 }
658 value_arena.deinit(gpa);
659 decl.value_arena = null;
660 decl.has_tv = false;
661 decl.owns_tv = false;
595 mod.destroyFunc(func);
662596 }
663597 }
664598
665 pub fn finalizeNewArena(decl: *Decl, arena: *std.heap.ArenaAllocator) !void {
666 assert(decl.value_arena == null);
667 const value_arena = try arena.allocator().create(ValueArena);
668 value_arena.* = .{ .state = arena.state };
669 decl.value_arena = value_arena;
670 }
671
672599 /// This name is relative to the containing namespace of the decl.
673600 /// The memory is owned by the containing File ZIR.
674 pub fn getName(decl: Decl) ?[:0]const u8 {
675 const zir = decl.getFileScope().zir;
601 pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 {
602 const zir = decl.getFileScope(mod).zir;
676603 return decl.getNameZir(zir);
677604 }
678605
......@@ -683,8 +610,8 @@ pub const Decl = struct {
683610 return zir.nullTerminatedString(name_index);
684611 }
685612
686 pub fn contentsHash(decl: Decl) std.zig.SrcHash {
687 const zir = decl.getFileScope().zir;
613 pub fn contentsHash(decl: Decl, mod: *Module) std.zig.SrcHash {
614 const zir = decl.getFileScope(mod).zir;
688615 return decl.contentsHashZir(zir);
689616 }
690617
......@@ -695,31 +622,31 @@ pub const Decl = struct {
695622 return contents_hash;
696623 }
697624
698 pub fn zirBlockIndex(decl: *const Decl) Zir.Inst.Index {
625 pub fn zirBlockIndex(decl: *const Decl, mod: *Module) Zir.Inst.Index {
699626 assert(decl.zir_decl_index != 0);
700 const zir = decl.getFileScope().zir;
627 const zir = decl.getFileScope(mod).zir;
701628 return zir.extra[decl.zir_decl_index + 6];
702629 }
703630
704 pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {
631 pub fn zirAlignRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
705632 if (!decl.has_align) return .none;
706633 assert(decl.zir_decl_index != 0);
707 const zir = decl.getFileScope().zir;
634 const zir = decl.getFileScope(mod).zir;
708635 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 8]);
709636 }
710637
711 pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref {
638 pub fn zirLinksectionRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
712639 if (!decl.has_linksection_or_addrspace) return .none;
713640 assert(decl.zir_decl_index != 0);
714 const zir = decl.getFileScope().zir;
641 const zir = decl.getFileScope(mod).zir;
715642 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align);
716643 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
717644 }
718645
719 pub fn zirAddrspaceRef(decl: Decl) Zir.Inst.Ref {
646 pub fn zirAddrspaceRef(decl: Decl, mod: *Module) Zir.Inst.Ref {
720647 if (!decl.has_linksection_or_addrspace) return .none;
721648 assert(decl.zir_decl_index != 0);
722 const zir = decl.getFileScope().zir;
649 const zir = decl.getFileScope(mod).zir;
723650 const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align) + 1;
724651 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
725652 }
......@@ -744,154 +671,167 @@ pub const Decl = struct {
744671 return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index));
745672 }
746673
747 pub fn srcLoc(decl: Decl) SrcLoc {
748 return decl.nodeOffsetSrcLoc(0);
674 pub fn srcLoc(decl: Decl, mod: *Module) SrcLoc {
675 return decl.nodeOffsetSrcLoc(0, mod);
749676 }
750677
751 pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32) SrcLoc {
678 pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, mod: *Module) SrcLoc {
752679 return .{
753 .file_scope = decl.getFileScope(),
680 .file_scope = decl.getFileScope(mod),
754681 .parent_decl_node = decl.src_node,
755682 .lazy = LazySrcLoc.nodeOffset(node_offset),
756683 };
757684 }
758685
759 pub fn srcToken(decl: Decl) Ast.TokenIndex {
760 const tree = &decl.getFileScope().tree;
686 pub fn srcToken(decl: Decl, mod: *Module) Ast.TokenIndex {
687 const tree = &decl.getFileScope(mod).tree;
761688 return tree.firstToken(decl.src_node);
762689 }
763690
764 pub fn srcByteOffset(decl: Decl) u32 {
765 const tree = &decl.getFileScope().tree;
691 pub fn srcByteOffset(decl: Decl, mod: *Module) u32 {
692 const tree = &decl.getFileScope(mod).tree;
766693 return tree.tokens.items(.start)[decl.srcToken()];
767694 }
768695
769696 pub fn renderFullyQualifiedName(decl: Decl, mod: *Module, writer: anytype) !void {
770 const unqualified_name = mem.sliceTo(decl.name, 0);
771697 if (decl.name_fully_qualified) {
772 return writer.writeAll(unqualified_name);
698 try writer.print("{}", .{decl.name.fmt(&mod.intern_pool)});
699 } else {
700 try mod.namespacePtr(decl.src_namespace).renderFullyQualifiedName(mod, decl.name, writer);
773701 }
774 return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer);
775702 }
776703
777704 pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void {
778 const unqualified_name = mem.sliceTo(decl.name, 0);
779 return decl.src_namespace.renderFullyQualifiedDebugName(mod, unqualified_name, writer);
705 return mod.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(mod, decl.name, writer);
780706 }
781707
782 pub fn getFullyQualifiedName(decl: Decl, mod: *Module) ![:0]u8 {
783 var buffer = std.ArrayList(u8).init(mod.gpa);
784 defer buffer.deinit();
785 try decl.renderFullyQualifiedName(mod, buffer.writer());
708 pub fn getFullyQualifiedName(decl: Decl, mod: *Module) !InternPool.NullTerminatedString {
709 if (decl.name_fully_qualified) return decl.name;
710
711 const ip = &mod.intern_pool;
712 const count = count: {
713 var count: usize = ip.stringToSlice(decl.name).len + 1;
714 var ns: Namespace.Index = decl.src_namespace;
715 while (true) {
716 const namespace = mod.namespacePtr(ns);
717 const ns_decl = mod.declPtr(namespace.getDeclIndex(mod));
718 count += ip.stringToSlice(ns_decl.name).len + 1;
719 ns = namespace.parent.unwrap() orelse {
720 count += namespace.file_scope.sub_file_path.len;
721 break :count count;
722 };
723 }
724 };
725
726 const gpa = mod.gpa;
727 const start = ip.string_bytes.items.len;
728 // Protects reads of interned strings from being reallocated during the call to
729 // renderFullyQualifiedName.
730 try ip.string_bytes.ensureUnusedCapacity(gpa, count);
731 decl.renderFullyQualifiedName(mod, ip.string_bytes.writer(gpa)) catch unreachable;
786732
787733 // Sanitize the name for nvptx which is more restrictive.
734 // TODO This should be handled by the backend, not the frontend. Have a
735 // look at how the C backend does it for inspiration.
788736 if (mod.comp.bin_file.options.target.cpu.arch.isNvptx()) {
789 for (buffer.items) |*byte| switch (byte.*) {
737 for (ip.string_bytes.items[start..]) |*byte| switch (byte.*) {
790738 '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
791739 else => {},
792740 };
793741 }
794742
795 return buffer.toOwnedSliceSentinel(0);
743 return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start);
796744 }
797745
798746 pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue {
799747 if (!decl.has_tv) return error.AnalysisFail;
800 return TypedValue{
801 .ty = decl.ty,
802 .val = decl.val,
803 };
748 return TypedValue{ .ty = decl.ty, .val = decl.val };
804749 }
805750
806 pub fn value(decl: *Decl) error{AnalysisFail}!Value {
807 return (try decl.typedValue()).val;
751 pub fn internValue(decl: *Decl, mod: *Module) Allocator.Error!InternPool.Index {
752 assert(decl.has_tv);
753 const ip_index = try decl.val.intern(decl.ty, mod);
754 decl.val = ip_index.toValue();
755 return ip_index;
808756 }
809757
810 pub fn isFunction(decl: Decl) !bool {
758 pub fn isFunction(decl: Decl, mod: *const Module) !bool {
811759 const tv = try decl.typedValue();
812 return tv.ty.zigTypeTag() == .Fn;
760 return tv.ty.zigTypeTag(mod) == .Fn;
813761 }
814762
815 /// If the Decl has a value and it is a struct, return it,
763 /// If the Decl owns its value and it is a struct, return it,
816764 /// otherwise null.
817 pub fn getStruct(decl: *Decl) ?*Struct {
818 if (!decl.owns_tv) return null;
819 const ty = (decl.val.castTag(.ty) orelse return null).data;
820 const struct_obj = (ty.castTag(.@"struct") orelse return null).data;
821 return struct_obj;
765 pub fn getOwnedStruct(decl: Decl, mod: *Module) ?*Struct {
766 return mod.structPtrUnwrap(decl.getOwnedStructIndex(mod));
767 }
768
769 pub fn getOwnedStructIndex(decl: Decl, mod: *Module) Struct.OptionalIndex {
770 if (!decl.owns_tv) return .none;
771 if (decl.val.ip_index == .none) return .none;
772 return mod.intern_pool.indexToStructType(decl.val.toIntern());
822773 }
823774
824 /// If the Decl has a value and it is a union, return it,
775 /// If the Decl owns its value and it is a union, return it,
825776 /// otherwise null.
826 pub fn getUnion(decl: *Decl) ?*Union {
777 pub fn getOwnedUnion(decl: Decl, mod: *Module) ?*Union {
827778 if (!decl.owns_tv) return null;
828 const ty = (decl.val.castTag(.ty) orelse return null).data;
829 const union_obj = (ty.cast(Type.Payload.Union) orelse return null).data;
830 return union_obj;
779 if (decl.val.ip_index == .none) return null;
780 return mod.typeToUnion(decl.val.toType());
831781 }
832782
833 /// If the Decl has a value and it is a function, return it,
783 /// If the Decl owns its value and it is a function, return it,
834784 /// otherwise null.
835 pub fn getFunction(decl: *const Decl) ?*Fn {
836 if (!decl.owns_tv) return null;
837 const func = (decl.val.castTag(.function) orelse return null).data;
838 return func;
785 pub fn getOwnedFunction(decl: Decl, mod: *Module) ?*Fn {
786 return mod.funcPtrUnwrap(decl.getOwnedFunctionIndex(mod));
839787 }
840788
841 /// If the Decl has a value and it is an extern function, returns it,
789 pub fn getOwnedFunctionIndex(decl: Decl, mod: *Module) Fn.OptionalIndex {
790 return if (decl.owns_tv) decl.val.getFunctionIndex(mod) else .none;
791 }
792
793 /// If the Decl owns its value and it is an extern function, returns it,
842794 /// otherwise null.
843 pub fn getExternFn(decl: *const Decl) ?*ExternFn {
844 if (!decl.owns_tv) return null;
845 const extern_fn = (decl.val.castTag(.extern_fn) orelse return null).data;
846 return extern_fn;
795 pub fn getOwnedExternFunc(decl: Decl, mod: *Module) ?InternPool.Key.ExternFunc {
796 return if (decl.owns_tv) decl.val.getExternFunc(mod) else null;
847797 }
848798
849 /// If the Decl has a value and it is a variable, returns it,
799 /// If the Decl owns its value and it is a variable, returns it,
850800 /// otherwise null.
851 pub fn getVariable(decl: *const Decl) ?*Var {
852 if (!decl.owns_tv) return null;
853 const variable = (decl.val.castTag(.variable) orelse return null).data;
854 return variable;
801 pub fn getOwnedVariable(decl: Decl, mod: *Module) ?InternPool.Key.Variable {
802 return if (decl.owns_tv) decl.val.getVariable(mod) else null;
855803 }
856804
857805 /// Gets the namespace that this Decl creates by being a struct, union,
858806 /// enum, or opaque.
859807 /// Only returns it if the Decl is the owner.
860 pub fn getInnerNamespace(decl: *Decl) ?*Namespace {
861 if (!decl.owns_tv) return null;
862 const ty = (decl.val.castTag(.ty) orelse return null).data;
863 switch (ty.tag()) {
864 .@"struct" => {
865 const struct_obj = ty.castTag(.@"struct").?.data;
866 return &struct_obj.namespace;
867 },
868 .enum_full, .enum_nonexhaustive => {
869 const enum_obj = ty.cast(Type.Payload.EnumFull).?.data;
870 return &enum_obj.namespace;
871 },
872 .empty_struct => {
873 return ty.castTag(.empty_struct).?.data;
874 },
875 .@"opaque" => {
876 const opaque_obj = ty.cast(Type.Payload.Opaque).?.data;
877 return &opaque_obj.namespace;
878 },
879 .@"union", .union_safety_tagged, .union_tagged => {
880 const union_obj = ty.cast(Type.Payload.Union).?.data;
881 return &union_obj.namespace;
808 pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex {
809 if (!decl.owns_tv) return .none;
810 return switch (decl.val.ip_index) {
811 .empty_struct_type => .none,
812 .none => .none,
813 else => switch (mod.intern_pool.indexToKey(decl.val.toIntern())) {
814 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
815 .struct_type => |struct_type| struct_type.namespace,
816 .union_type => |union_type| mod.unionPtr(union_type.index).namespace.toOptional(),
817 .enum_type => |enum_type| enum_type.namespace,
818 else => .none,
882819 },
820 };
821 }
883822
884 else => return null,
885 }
823 /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer.
824 pub fn getOwnedInnerNamespace(decl: Decl, mod: *Module) ?*Namespace {
825 return mod.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(mod));
886826 }
887827
888828 pub fn dump(decl: *Decl) void {
889829 const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src);
890 std.debug.print("{s}:{d}:{d} name={s} status={s}", .{
830 std.debug.print("{s}:{d}:{d} name={d} status={s}", .{
891831 decl.scope.sub_file_path,
892832 loc.line + 1,
893833 loc.column + 1,
894 mem.sliceTo(decl.name, 0),
834 @enumToInt(decl.name),
895835 @tagName(decl.analysis),
896836 });
897837 if (decl.has_tv) {
......@@ -900,8 +840,8 @@ pub const Decl = struct {
900840 std.debug.print("\n", .{});
901841 }
902842
903 pub fn getFileScope(decl: Decl) *File {
904 return decl.src_namespace.file_scope;
843 pub fn getFileScope(decl: Decl, mod: *Module) *File {
844 return mod.namespacePtr(decl.src_namespace).file_scope;
905845 }
906846
907847 pub fn removeDependant(decl: *Decl, other: Decl.Index) void {
......@@ -912,25 +852,29 @@ pub const Decl = struct {
912852 assert(decl.dependencies.swapRemove(other));
913853 }
914854
915 pub fn isExtern(decl: Decl) bool {
855 pub fn isExtern(decl: Decl, mod: *Module) bool {
916856 assert(decl.has_tv);
917 return switch (decl.val.tag()) {
918 .extern_fn => true,
919 .variable => decl.val.castTag(.variable).?.data.init.tag() == .unreachable_value,
857 return switch (mod.intern_pool.indexToKey(decl.val.toIntern())) {
858 .variable => |variable| variable.is_extern,
859 .extern_func => true,
920860 else => false,
921861 };
922862 }
923863
924 pub fn getAlignment(decl: Decl, target: Target) u32 {
864 pub fn getAlignment(decl: Decl, mod: *Module) u32 {
925865 assert(decl.has_tv);
926866 if (decl.@"align" != 0) {
927867 // Explicit alignment.
928868 return decl.@"align";
929869 } else {
930870 // Natural alignment.
931 return decl.ty.abiAlignment(target);
871 return decl.ty.abiAlignment(mod);
932872 }
933873 }
874
875 pub fn intern(decl: *Decl, mod: *Module) Allocator.Error!void {
876 decl.val = (try decl.val.intern(decl.ty, mod)).toValue();
877 }
934878};
935879
936880/// This state is attached to every Decl when Module emit_h is non-null.
......@@ -938,38 +882,6 @@ pub const EmitH = struct {
938882 fwd_decl: ArrayListUnmanaged(u8) = .{},
939883};
940884
941/// Represents the data that an explicit error set syntax provides.
942pub const ErrorSet = struct {
943 /// The Decl that corresponds to the error set itself.
944 owner_decl: Decl.Index,
945 /// The string bytes are stored in the owner Decl arena.
946 /// These must be in sorted order. See sortNames.
947 names: NameMap,
948
949 pub const NameMap = std.StringArrayHashMapUnmanaged(void);
950
951 pub fn srcLoc(self: ErrorSet, mod: *Module) SrcLoc {
952 const owner_decl = mod.declPtr(self.owner_decl);
953 return .{
954 .file_scope = owner_decl.getFileScope(),
955 .parent_decl_node = owner_decl.src_node,
956 .lazy = LazySrcLoc.nodeOffset(0),
957 };
958 }
959
960 /// sort the NameMap. This should be called whenever the map is modified.
961 /// alloc should be the allocator used for the NameMap data.
962 pub fn sortNames(names: *NameMap) void {
963 const Context = struct {
964 keys: [][]const u8,
965 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {
966 return std.mem.lessThan(u8, ctx.keys[a_index], ctx.keys[b_index]);
967 }
968 };
969 names.sort(Context{ .keys = names.keys() });
970 }
971};
972
973885pub const PropertyBoolean = enum { no, yes, unknown, wip };
974886
975887/// Represents the data that a struct declaration provides.
......@@ -977,7 +889,7 @@ pub const Struct = struct {
977889 /// Set of field names in declaration order.
978890 fields: Fields,
979891 /// Represents the declarations inside this struct.
980 namespace: Namespace,
892 namespace: Namespace.Index,
981893 /// The Decl that corresponds to the struct itself.
982894 owner_decl: Decl.Index,
983895 /// Index of the struct_decl ZIR instruction.
......@@ -989,7 +901,7 @@ pub const Struct = struct {
989901 /// If the layout is packed, this is the backing integer type of the packed struct.
990902 /// Whether zig chooses this type or the user specifies it, it is stored here.
991903 /// This will be set to the noreturn type until status is `have_layout`.
992 backing_int_ty: Type = Type.initTag(.noreturn),
904 backing_int_ty: Type = Type.noreturn,
993905 status: enum {
994906 none,
995907 field_types_wip,
......@@ -1011,15 +923,37 @@ pub const Struct = struct {
1011923 is_tuple: bool,
1012924 assumed_runtime_bits: bool = false,
1013925
1014 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
926 pub const Index = enum(u32) {
927 _,
928
929 pub fn toOptional(i: Index) OptionalIndex {
930 return @intToEnum(OptionalIndex, @enumToInt(i));
931 }
932 };
933
934 pub const OptionalIndex = enum(u32) {
935 none = std.math.maxInt(u32),
936 _,
937
938 pub fn init(oi: ?Index) OptionalIndex {
939 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
940 }
941
942 pub fn unwrap(oi: OptionalIndex) ?Index {
943 if (oi == .none) return null;
944 return @intToEnum(Index, @enumToInt(oi));
945 }
946 };
947
948 pub const Fields = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, Field);
1015949
1016950 /// The `Type` and `Value` memory is owned by the arena of the Struct's owner_decl.
1017951 pub const Field = struct {
1018952 /// Uses `noreturn` to indicate `anytype`.
1019953 /// undefined until `status` is >= `have_field_types`.
1020954 ty: Type,
1021 /// Uses `unreachable_value` to indicate no default.
1022 default_val: Value,
955 /// Uses `none` to indicate no default.
956 default_val: InternPool.Index,
1023957 /// Zero means to use the ABI alignment of the type.
1024958 abi_align: u32,
1025959 /// undefined until `status` is `have_layout`.
......@@ -1030,7 +964,7 @@ pub const Struct = struct {
1030964 /// Returns the field alignment. If the struct is packed, returns 0.
1031965 pub fn alignment(
1032966 field: Field,
1033 target: Target,
967 mod: *Module,
1034968 layout: std.builtin.Type.ContainerLayout,
1035969 ) u32 {
1036970 if (field.abi_align != 0) {
......@@ -1038,24 +972,26 @@ pub const Struct = struct {
1038972 return field.abi_align;
1039973 }
1040974
975 const target = mod.getTarget();
976
1041977 switch (layout) {
1042978 .Packed => return 0,
1043979 .Auto => {
1044980 if (target.ofmt == .c) {
1045 return alignmentExtern(field, target);
981 return alignmentExtern(field, mod);
1046982 } else {
1047 return field.ty.abiAlignment(target);
983 return field.ty.abiAlignment(mod);
1048984 }
1049985 },
1050 .Extern => return alignmentExtern(field, target),
986 .Extern => return alignmentExtern(field, mod),
1051987 }
1052988 }
1053989
1054 pub fn alignmentExtern(field: Field, target: Target) u32 {
990 pub fn alignmentExtern(field: Field, mod: *Module) u32 {
1055991 // This logic is duplicated in Type.abiAlignmentAdvanced.
1056 const ty_abi_align = field.ty.abiAlignment(target);
992 const ty_abi_align = field.ty.abiAlignment(mod);
1057993
1058 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
994 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
1059995 // The C ABI requires 128 bit integer fields of structs
1060996 // to be 16-bytes aligned.
1061997 return @max(ty_abi_align, 16);
......@@ -1069,39 +1005,12 @@ pub const Struct = struct {
10691005 /// runtime version of the struct.
10701006 pub const omitted_field = std.math.maxInt(u32);
10711007
1072 pub fn getFullyQualifiedName(s: *Struct, mod: *Module) ![:0]u8 {
1008 pub fn getFullyQualifiedName(s: *Struct, mod: *Module) !InternPool.NullTerminatedString {
10731009 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
10741010 }
10751011
10761012 pub fn srcLoc(s: Struct, mod: *Module) SrcLoc {
1077 const owner_decl = mod.declPtr(s.owner_decl);
1078 return .{
1079 .file_scope = owner_decl.getFileScope(),
1080 .parent_decl_node = owner_decl.src_node,
1081 .lazy = LazySrcLoc.nodeOffset(0),
1082 };
1083 }
1084
1085 pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc {
1086 @setCold(true);
1087 const owner_decl = mod.declPtr(s.owner_decl);
1088 const file = owner_decl.getFileScope();
1089 const tree = file.getTree(mod.gpa) catch |err| {
1090 // In this case we emit a warning + a less precise source location.
1091 log.warn("unable to load {s}: {s}", .{
1092 file.sub_file_path, @errorName(err),
1093 });
1094 return s.srcLoc(mod);
1095 };
1096 const node = owner_decl.relativeToNodeIndex(0);
1097
1098 var buf: [2]Ast.Node.Index = undefined;
1099 if (tree.fullContainerDecl(&buf, node)) |container_decl| {
1100 return queryFieldSrc(tree.*, query, file, container_decl);
1101 } else {
1102 // This struct was generated using @Type
1103 return s.srcLoc(mod);
1104 }
1013 return mod.declPtr(s.owner_decl).srcLoc(mod);
11051014 }
11061015
11071016 pub fn haveFieldTypes(s: Struct) bool {
......@@ -1132,7 +1041,7 @@ pub const Struct = struct {
11321041 };
11331042 }
11341043
1135 pub fn packedFieldBitOffset(s: Struct, target: Target, index: usize) u16 {
1044 pub fn packedFieldBitOffset(s: Struct, mod: *Module, index: usize) u16 {
11361045 assert(s.layout == .Packed);
11371046 assert(s.haveLayout());
11381047 var bit_sum: u64 = 0;
......@@ -1140,12 +1049,13 @@ pub const Struct = struct {
11401049 if (i == index) {
11411050 return @intCast(u16, bit_sum);
11421051 }
1143 bit_sum += field.ty.bitSize(target);
1052 bit_sum += field.ty.bitSize(mod);
11441053 }
11451054 unreachable; // index out of bounds
11461055 }
11471056
11481057 pub const RuntimeFieldIterator = struct {
1058 module: *Module,
11491059 struct_obj: *const Struct,
11501060 index: u32 = 0,
11511061
......@@ -1155,6 +1065,7 @@ pub const Struct = struct {
11551065 };
11561066
11571067 pub fn next(it: *RuntimeFieldIterator) ?FieldAndIndex {
1068 const mod = it.module;
11581069 while (true) {
11591070 var i = it.index;
11601071 it.index += 1;
......@@ -1167,120 +1078,19 @@ pub const Struct = struct {
11671078 }
11681079 const field = it.struct_obj.fields.values()[i];
11691080
1170 if (!field.is_comptime and field.ty.hasRuntimeBits()) {
1081 if (!field.is_comptime and field.ty.hasRuntimeBits(mod)) {
11711082 return FieldAndIndex{ .index = i, .field = field };
11721083 }
11731084 }
11741085 }
11751086 };
11761087
1177 pub fn runtimeFieldIterator(s: *const Struct) RuntimeFieldIterator {
1178 return .{ .struct_obj = s };
1179 }
1180};
1181
1182/// Represents the data that an enum declaration provides, when the fields
1183/// are auto-numbered, and there are no declarations. The integer tag type
1184/// is inferred to be the smallest power of two unsigned int that fits
1185/// the number of fields.
1186pub const EnumSimple = struct {
1187 /// The Decl that corresponds to the enum itself.
1188 owner_decl: Decl.Index,
1189 /// Set of field names in declaration order.
1190 fields: NameMap,
1191
1192 pub const NameMap = EnumFull.NameMap;
1193
1194 pub fn srcLoc(self: EnumSimple, mod: *Module) SrcLoc {
1195 const owner_decl = mod.declPtr(self.owner_decl);
1196 return .{
1197 .file_scope = owner_decl.getFileScope(),
1198 .parent_decl_node = owner_decl.src_node,
1199 .lazy = LazySrcLoc.nodeOffset(0),
1200 };
1201 }
1202};
1203
1204/// Represents the data that an enum declaration provides, when there are no
1205/// declarations. However an integer tag type is provided, and the enum tag values
1206/// are explicitly provided.
1207pub const EnumNumbered = struct {
1208 /// The Decl that corresponds to the enum itself.
1209 owner_decl: Decl.Index,
1210 /// An integer type which is used for the numerical value of the enum.
1211 /// Whether zig chooses this type or the user specifies it, it is stored here.
1212 tag_ty: Type,
1213 /// Set of field names in declaration order.
1214 fields: NameMap,
1215 /// Maps integer tag value to field index.
1216 /// Entries are in declaration order, same as `fields`.
1217 /// If this hash map is empty, it means the enum tags are auto-numbered.
1218 values: ValueMap,
1219
1220 pub const NameMap = EnumFull.NameMap;
1221 pub const ValueMap = EnumFull.ValueMap;
1222
1223 pub fn srcLoc(self: EnumNumbered, mod: *Module) SrcLoc {
1224 const owner_decl = mod.declPtr(self.owner_decl);
1225 return .{
1226 .file_scope = owner_decl.getFileScope(),
1227 .parent_decl_node = owner_decl.src_node,
1228 .lazy = LazySrcLoc.nodeOffset(0),
1229 };
1230 }
1231};
1232
1233/// Represents the data that an enum declaration provides, when there is
1234/// at least one tag value explicitly specified, or at least one declaration.
1235pub const EnumFull = struct {
1236 /// The Decl that corresponds to the enum itself.
1237 owner_decl: Decl.Index,
1238 /// An integer type which is used for the numerical value of the enum.
1239 /// Whether zig chooses this type or the user specifies it, it is stored here.
1240 tag_ty: Type,
1241 /// Set of field names in declaration order.
1242 fields: NameMap,
1243 /// Maps integer tag value to field index.
1244 /// Entries are in declaration order, same as `fields`.
1245 /// If this hash map is empty, it means the enum tags are auto-numbered.
1246 values: ValueMap,
1247 /// Represents the declarations inside this enum.
1248 namespace: Namespace,
1249 /// true if zig inferred this tag type, false if user specified it
1250 tag_ty_inferred: bool,
1251
1252 pub const NameMap = std.StringArrayHashMapUnmanaged(void);
1253 pub const ValueMap = std.ArrayHashMapUnmanaged(Value, void, Value.ArrayHashContext, false);
1254
1255 pub fn srcLoc(self: EnumFull, mod: *Module) SrcLoc {
1256 const owner_decl = mod.declPtr(self.owner_decl);
1088 pub fn runtimeFieldIterator(s: *const Struct, module: *Module) RuntimeFieldIterator {
12571089 return .{
1258 .file_scope = owner_decl.getFileScope(),
1259 .parent_decl_node = owner_decl.src_node,
1260 .lazy = LazySrcLoc.nodeOffset(0),
1090 .struct_obj = s,
1091 .module = module,
12611092 };
12621093 }
1263
1264 pub fn fieldSrcLoc(e: EnumFull, mod: *Module, query: FieldSrcQuery) SrcLoc {
1265 @setCold(true);
1266 const owner_decl = mod.declPtr(e.owner_decl);
1267 const file = owner_decl.getFileScope();
1268 const tree = file.getTree(mod.gpa) catch |err| {
1269 // In this case we emit a warning + a less precise source location.
1270 log.warn("unable to load {s}: {s}", .{
1271 file.sub_file_path, @errorName(err),
1272 });
1273 return e.srcLoc(mod);
1274 };
1275 const node = owner_decl.relativeToNodeIndex(0);
1276 var buf: [2]Ast.Node.Index = undefined;
1277 if (tree.fullContainerDecl(&buf, node)) |container_decl| {
1278 return queryFieldSrc(tree.*, query, file, container_decl);
1279 } else {
1280 // This enum was generated using @Type
1281 return e.srcLoc(mod);
1282 }
1283 }
12841094};
12851095
12861096pub const Union = struct {
......@@ -1293,7 +1103,7 @@ pub const Union = struct {
12931103 /// Set of field names in declaration order.
12941104 fields: Fields,
12951105 /// Represents the declarations inside this union.
1296 namespace: Namespace,
1106 namespace: Namespace.Index,
12971107 /// The Decl that corresponds to the union itself.
12981108 owner_decl: Decl.Index,
12991109 /// Index of the union_decl ZIR instruction.
......@@ -1314,6 +1124,28 @@ pub const Union = struct {
13141124 requires_comptime: PropertyBoolean = .unknown,
13151125 assumed_runtime_bits: bool = false,
13161126
1127 pub const Index = enum(u32) {
1128 _,
1129
1130 pub fn toOptional(i: Index) OptionalIndex {
1131 return @intToEnum(OptionalIndex, @enumToInt(i));
1132 }
1133 };
1134
1135 pub const OptionalIndex = enum(u32) {
1136 none = std.math.maxInt(u32),
1137 _,
1138
1139 pub fn init(oi: ?Index) OptionalIndex {
1140 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
1141 }
1142
1143 pub fn unwrap(oi: OptionalIndex) ?Index {
1144 if (oi == .none) return null;
1145 return @intToEnum(Index, @enumToInt(oi));
1146 }
1147 };
1148
13171149 pub const Field = struct {
13181150 /// undefined until `status` is `have_field_types` or `have_layout`.
13191151 ty: Type,
......@@ -1323,52 +1155,30 @@ pub const Union = struct {
13231155 /// Returns the field alignment, assuming the union is not packed.
13241156 /// Keep implementation in sync with `Sema.unionFieldAlignment`.
13251157 /// Prefer to call that function instead of this one during Sema.
1326 pub fn normalAlignment(field: Field, target: Target) u32 {
1158 pub fn normalAlignment(field: Field, mod: *Module) u32 {
13271159 if (field.abi_align == 0) {
1328 return field.ty.abiAlignment(target);
1160 return field.ty.abiAlignment(mod);
13291161 } else {
13301162 return field.abi_align;
13311163 }
13321164 }
13331165 };
13341166
1335 pub const Fields = std.StringArrayHashMapUnmanaged(Field);
1167 pub const Fields = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, Field);
13361168
1337 pub fn getFullyQualifiedName(s: *Union, mod: *Module) ![:0]u8 {
1169 pub fn getFullyQualifiedName(s: *Union, mod: *Module) !InternPool.NullTerminatedString {
13381170 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
13391171 }
13401172
13411173 pub fn srcLoc(self: Union, mod: *Module) SrcLoc {
13421174 const owner_decl = mod.declPtr(self.owner_decl);
13431175 return .{
1344 .file_scope = owner_decl.getFileScope(),
1176 .file_scope = owner_decl.getFileScope(mod),
13451177 .parent_decl_node = owner_decl.src_node,
13461178 .lazy = LazySrcLoc.nodeOffset(0),
13471179 };
13481180 }
13491181
1350 pub fn fieldSrcLoc(u: Union, mod: *Module, query: FieldSrcQuery) SrcLoc {
1351 @setCold(true);
1352 const owner_decl = mod.declPtr(u.owner_decl);
1353 const file = owner_decl.getFileScope();
1354 const tree = file.getTree(mod.gpa) catch |err| {
1355 // In this case we emit a warning + a less precise source location.
1356 log.warn("unable to load {s}: {s}", .{
1357 file.sub_file_path, @errorName(err),
1358 });
1359 return u.srcLoc(mod);
1360 };
1361 const node = owner_decl.relativeToNodeIndex(0);
1362
1363 var buf: [2]Ast.Node.Index = undefined;
1364 if (tree.fullContainerDecl(&buf, node)) |container_decl| {
1365 return queryFieldSrc(tree.*, query, file, container_decl);
1366 } else {
1367 // This union was generated using @Type
1368 return u.srcLoc(mod);
1369 }
1370 }
1371
13721182 pub fn haveFieldTypes(u: Union) bool {
13731183 return switch (u.status) {
13741184 .none,
......@@ -1383,22 +1193,22 @@ pub const Union = struct {
13831193 };
13841194 }
13851195
1386 pub fn hasAllZeroBitFieldTypes(u: Union) bool {
1196 pub fn hasAllZeroBitFieldTypes(u: Union, mod: *Module) bool {
13871197 assert(u.haveFieldTypes());
13881198 for (u.fields.values()) |field| {
1389 if (field.ty.hasRuntimeBits()) return false;
1199 if (field.ty.hasRuntimeBits(mod)) return false;
13901200 }
13911201 return true;
13921202 }
13931203
1394 pub fn mostAlignedField(u: Union, target: Target) u32 {
1204 pub fn mostAlignedField(u: Union, mod: *Module) u32 {
13951205 assert(u.haveFieldTypes());
13961206 var most_alignment: u32 = 0;
13971207 var most_index: usize = undefined;
13981208 for (u.fields.values(), 0..) |field, i| {
1399 if (!field.ty.hasRuntimeBits()) continue;
1209 if (!field.ty.hasRuntimeBits(mod)) continue;
14001210
1401 const field_align = field.normalAlignment(target);
1211 const field_align = field.normalAlignment(mod);
14021212 if (field_align > most_alignment) {
14031213 most_alignment = field_align;
14041214 most_index = i;
......@@ -1408,20 +1218,20 @@ pub const Union = struct {
14081218 }
14091219
14101220 /// Returns 0 if the union is represented with 0 bits at runtime.
1411 pub fn abiAlignment(u: Union, target: Target, have_tag: bool) u32 {
1221 pub fn abiAlignment(u: Union, mod: *Module, have_tag: bool) u32 {
14121222 var max_align: u32 = 0;
1413 if (have_tag) max_align = u.tag_ty.abiAlignment(target);
1223 if (have_tag) max_align = u.tag_ty.abiAlignment(mod);
14141224 for (u.fields.values()) |field| {
1415 if (!field.ty.hasRuntimeBits()) continue;
1225 if (!field.ty.hasRuntimeBits(mod)) continue;
14161226
1417 const field_align = field.normalAlignment(target);
1227 const field_align = field.normalAlignment(mod);
14181228 max_align = @max(max_align, field_align);
14191229 }
14201230 return max_align;
14211231 }
14221232
1423 pub fn abiSize(u: Union, target: Target, have_tag: bool) u64 {
1424 return u.getLayout(target, have_tag).abi_size;
1233 pub fn abiSize(u: Union, mod: *Module, have_tag: bool) u64 {
1234 return u.getLayout(mod, have_tag).abi_size;
14251235 }
14261236
14271237 pub const Layout = struct {
......@@ -1451,7 +1261,7 @@ pub const Union = struct {
14511261 };
14521262 }
14531263
1454 pub fn getLayout(u: Union, target: Target, have_tag: bool) Layout {
1264 pub fn getLayout(u: Union, mod: *Module, have_tag: bool) Layout {
14551265 assert(u.haveLayout());
14561266 var most_aligned_field: u32 = undefined;
14571267 var most_aligned_field_size: u64 = undefined;
......@@ -1460,16 +1270,16 @@ pub const Union = struct {
14601270 var payload_align: u32 = 0;
14611271 const fields = u.fields.values();
14621272 for (fields, 0..) |field, i| {
1463 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
1273 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
14641274
14651275 const field_align = a: {
14661276 if (field.abi_align == 0) {
1467 break :a field.ty.abiAlignment(target);
1277 break :a field.ty.abiAlignment(mod);
14681278 } else {
14691279 break :a field.abi_align;
14701280 }
14711281 };
1472 const field_size = field.ty.abiSize(target);
1282 const field_size = field.ty.abiSize(mod);
14731283 if (field_size > payload_size) {
14741284 payload_size = field_size;
14751285 biggest_field = @intCast(u32, i);
......@@ -1481,7 +1291,7 @@ pub const Union = struct {
14811291 }
14821292 }
14831293 payload_align = @max(payload_align, 1);
1484 if (!have_tag or !u.tag_ty.hasRuntimeBits()) {
1294 if (!have_tag or !u.tag_ty.hasRuntimeBits(mod)) {
14851295 return .{
14861296 .abi_size = std.mem.alignForwardGeneric(u64, payload_size, payload_align),
14871297 .abi_align = payload_align,
......@@ -1497,8 +1307,8 @@ pub const Union = struct {
14971307 }
14981308 // Put the tag before or after the payload depending on which one's
14991309 // alignment is greater.
1500 const tag_size = u.tag_ty.abiSize(target);
1501 const tag_align = @max(1, u.tag_ty.abiAlignment(target));
1310 const tag_size = u.tag_ty.abiSize(mod);
1311 const tag_align = @max(1, u.tag_ty.abiAlignment(mod));
15021312 var size: u64 = 0;
15031313 var padding: u32 = undefined;
15041314 if (tag_align >= payload_align) {
......@@ -1533,26 +1343,6 @@ pub const Union = struct {
15331343 }
15341344};
15351345
1536pub const Opaque = struct {
1537 /// The Decl that corresponds to the opaque itself.
1538 owner_decl: Decl.Index,
1539 /// Represents the declarations inside this opaque.
1540 namespace: Namespace,
1541
1542 pub fn srcLoc(self: Opaque, mod: *Module) SrcLoc {
1543 const owner_decl = mod.declPtr(self.owner_decl);
1544 return .{
1545 .file_scope = owner_decl.getFileScope(),
1546 .parent_decl_node = owner_decl.src_node,
1547 .lazy = LazySrcLoc.nodeOffset(0),
1548 };
1549 }
1550
1551 pub fn getFullyQualifiedName(s: *Opaque, mod: *Module) ![:0]u8 {
1552 return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod);
1553 }
1554};
1555
15561346/// Some extern function struct memory is owned by the Decl's TypedValue.Managed
15571347/// arena allocator.
15581348pub const ExternFn = struct {
......@@ -1630,12 +1420,27 @@ pub const Fn = struct {
16301420 is_noinline: bool,
16311421 calls_or_awaits_errorable_fn: bool = false,
16321422
1633 /// Any inferred error sets that this function owns, both its own inferred error set and
1634 /// inferred error sets of any inline/comptime functions called. Not to be confused
1635 /// with inferred error sets of generic instantiations of this function, which are
1636 /// *not* tracked here - they are tracked in the new `Fn` object created for the
1637 /// instantiations.
1638 inferred_error_sets: InferredErrorSetList = .{},
1423 pub const Index = enum(u32) {
1424 _,
1425
1426 pub fn toOptional(i: Index) OptionalIndex {
1427 return @intToEnum(OptionalIndex, @enumToInt(i));
1428 }
1429 };
1430
1431 pub const OptionalIndex = enum(u32) {
1432 none = std.math.maxInt(u32),
1433 _,
1434
1435 pub fn init(oi: ?Index) OptionalIndex {
1436 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
1437 }
1438
1439 pub fn unwrap(oi: OptionalIndex) ?Index {
1440 if (oi == .none) return null;
1441 return @intToEnum(Index, @enumToInt(oi));
1442 }
1443 };
16391444
16401445 pub const Analysis = enum {
16411446 /// This function has not yet undergone analysis, because we have not
......@@ -1662,16 +1467,16 @@ pub const Fn = struct {
16621467 /// or comptime functions.
16631468 pub const InferredErrorSet = struct {
16641469 /// The function from which this error set originates.
1665 func: *Fn,
1470 func: Fn.Index,
16661471
16671472 /// All currently known errors that this error set contains. This includes
16681473 /// direct additions via `return error.Foo;`, and possibly also errors that
16691474 /// are returned from any dependent functions. When the inferred error set is
16701475 /// fully resolved, this map contains all the errors that the function might return.
1671 errors: ErrorSet.NameMap = .{},
1476 errors: NameMap = .{},
16721477
16731478 /// Other inferred error sets which this inferred error set should include.
1674 inferred_error_sets: std.AutoArrayHashMapUnmanaged(*InferredErrorSet, void) = .{},
1479 inferred_error_sets: std.AutoArrayHashMapUnmanaged(InferredErrorSet.Index, void) = .{},
16751480
16761481 /// Whether the function returned anyerror. This is true if either of
16771482 /// the dependent functions returns anyerror.
......@@ -1681,52 +1486,57 @@ pub const Fn = struct {
16811486 /// can skip resolving any dependents of this inferred error set.
16821487 is_resolved: bool = false,
16831488
1684 pub fn addErrorSet(self: *InferredErrorSet, gpa: Allocator, err_set_ty: Type) !void {
1685 switch (err_set_ty.tag()) {
1686 .error_set => {
1687 const names = err_set_ty.castTag(.error_set).?.data.names.keys();
1688 for (names) |name| {
1689 try self.errors.put(gpa, name, {});
1690 }
1691 },
1692 .error_set_single => {
1693 const name = err_set_ty.castTag(.error_set_single).?.data;
1694 try self.errors.put(gpa, name, {});
1695 },
1696 .error_set_inferred => {
1697 const ies = err_set_ty.castTag(.error_set_inferred).?.data;
1698 try self.inferred_error_sets.put(gpa, ies, {});
1699 },
1700 .error_set_merged => {
1701 const names = err_set_ty.castTag(.error_set_merged).?.data.keys();
1702 for (names) |name| {
1703 try self.errors.put(gpa, name, {});
1704 }
1705 },
1706 .anyerror => {
1489 pub const NameMap = std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void);
1490
1491 pub const Index = enum(u32) {
1492 _,
1493
1494 pub fn toOptional(i: InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1495 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(i));
1496 }
1497 };
1498
1499 pub const OptionalIndex = enum(u32) {
1500 none = std.math.maxInt(u32),
1501 _,
1502
1503 pub fn init(oi: ?InferredErrorSet.Index) InferredErrorSet.OptionalIndex {
1504 return @intToEnum(InferredErrorSet.OptionalIndex, @enumToInt(oi orelse return .none));
1505 }
1506
1507 pub fn unwrap(oi: InferredErrorSet.OptionalIndex) ?InferredErrorSet.Index {
1508 if (oi == .none) return null;
1509 return @intToEnum(InferredErrorSet.Index, @enumToInt(oi));
1510 }
1511 };
1512
1513 pub fn addErrorSet(
1514 self: *InferredErrorSet,
1515 err_set_ty: Type,
1516 ip: *InternPool,
1517 gpa: Allocator,
1518 ) !void {
1519 switch (err_set_ty.toIntern()) {
1520 .anyerror_type => {
17071521 self.is_anyerror = true;
17081522 },
1709 else => unreachable,
1523 else => switch (ip.indexToKey(err_set_ty.toIntern())) {
1524 .error_set_type => |error_set_type| {
1525 for (error_set_type.names) |name| {
1526 try self.errors.put(gpa, name, {});
1527 }
1528 },
1529 .inferred_error_set_type => |ies_index| {
1530 try self.inferred_error_sets.put(gpa, ies_index, {});
1531 },
1532 else => unreachable,
1533 },
17101534 }
17111535 }
17121536 };
17131537
1714 pub const InferredErrorSetList = std.SinglyLinkedList(InferredErrorSet);
1715 pub const InferredErrorSetListNode = InferredErrorSetList.Node;
1716
1717 pub fn deinit(func: *Fn, gpa: Allocator) void {
1718 var it = func.inferred_error_sets.first;
1719 while (it) |node| {
1720 const next = node.next;
1721 node.data.errors.deinit(gpa);
1722 node.data.inferred_error_sets.deinit(gpa);
1723 gpa.destroy(node);
1724 it = next;
1725 }
1726 }
1727
17281538 pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool {
1729 const file = mod.declPtr(func.owner_decl).getFileScope();
1539 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
17301540
17311541 const tags = file.zir.instructions.items(.tag);
17321542
......@@ -1741,7 +1551,7 @@ pub const Fn = struct {
17411551 }
17421552
17431553 pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 {
1744 const file = mod.declPtr(func.owner_decl).getFileScope();
1554 const file = mod.declPtr(func.owner_decl).getFileScope(mod);
17451555
17461556 const tags = file.zir.instructions.items(.tag);
17471557 const data = file.zir.instructions.items(.data);
......@@ -1764,7 +1574,7 @@ pub const Fn = struct {
17641574
17651575 pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool {
17661576 const owner_decl = mod.declPtr(func.owner_decl);
1767 const zir = owner_decl.getFileScope().zir;
1577 const zir = owner_decl.getFileScope(mod).zir;
17681578 const zir_tags = zir.instructions.items(.tag);
17691579 switch (zir_tags[func.zir_body_inst]) {
17701580 .func => return false,
......@@ -1779,46 +1589,24 @@ pub const Fn = struct {
17791589 }
17801590};
17811591
1782pub const Var = struct {
1783 /// if is_extern == true this is undefined
1784 init: Value,
1785 owner_decl: Decl.Index,
1786
1787 /// Library name if specified.
1788 /// For example `extern "c" var stderrp = ...` would have 'c' as library name.
1789 /// Allocated with Module's allocator; outlives the ZIR code.
1790 lib_name: ?[*:0]const u8,
1791
1792 is_extern: bool,
1793 is_mutable: bool,
1794 is_threadlocal: bool,
1795 is_weak_linkage: bool,
1796
1797 pub fn deinit(variable: *Var, gpa: Allocator) void {
1798 if (variable.lib_name) |lib_name| {
1799 gpa.free(mem.sliceTo(lib_name, 0));
1800 }
1801 }
1802};
1803
18041592pub const DeclAdapter = struct {
18051593 mod: *Module,
18061594
1807 pub fn hash(self: @This(), s: []const u8) u32 {
1595 pub fn hash(self: @This(), s: InternPool.NullTerminatedString) u32 {
18081596 _ = self;
1809 return @truncate(u32, std.hash.Wyhash.hash(0, s));
1597 return std.hash.uint32(@enumToInt(s));
18101598 }
18111599
1812 pub fn eql(self: @This(), a: []const u8, b_decl_index: Decl.Index, b_index: usize) bool {
1600 pub fn eql(self: @This(), a: InternPool.NullTerminatedString, b_decl_index: Decl.Index, b_index: usize) bool {
18131601 _ = b_index;
18141602 const b_decl = self.mod.declPtr(b_decl_index);
1815 return mem.eql(u8, a, mem.sliceTo(b_decl.name, 0));
1603 return a == b_decl.name;
18161604 }
18171605};
18181606
18191607/// The container that structs, enums, unions, and opaques have.
18201608pub const Namespace = struct {
1821 parent: ?*Namespace,
1609 parent: OptionalIndex,
18221610 file_scope: *File,
18231611 /// Will be a struct, enum, union, or opaque.
18241612 ty: Type,
......@@ -1836,21 +1624,41 @@ pub const Namespace = struct {
18361624 /// Value is whether the usingnamespace decl is marked `pub`.
18371625 usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{},
18381626
1627 pub const Index = enum(u32) {
1628 _,
1629
1630 pub fn toOptional(i: Index) OptionalIndex {
1631 return @intToEnum(OptionalIndex, @enumToInt(i));
1632 }
1633 };
1634
1635 pub const OptionalIndex = enum(u32) {
1636 none = std.math.maxInt(u32),
1637 _,
1638
1639 pub fn init(oi: ?Index) OptionalIndex {
1640 return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none));
1641 }
1642
1643 pub fn unwrap(oi: OptionalIndex) ?Index {
1644 if (oi == .none) return null;
1645 return @intToEnum(Index, @enumToInt(oi));
1646 }
1647 };
1648
18391649 const DeclContext = struct {
18401650 module: *Module,
18411651
18421652 pub fn hash(ctx: @This(), decl_index: Decl.Index) u32 {
18431653 const decl = ctx.module.declPtr(decl_index);
1844 return @truncate(u32, std.hash.Wyhash.hash(0, mem.sliceTo(decl.name, 0)));
1654 return std.hash.uint32(@enumToInt(decl.name));
18451655 }
18461656
18471657 pub fn eql(ctx: @This(), a_decl_index: Decl.Index, b_decl_index: Decl.Index, b_index: usize) bool {
18481658 _ = b_index;
18491659 const a_decl = ctx.module.declPtr(a_decl_index);
18501660 const b_decl = ctx.module.declPtr(b_decl_index);
1851 const a_name = mem.sliceTo(a_decl.name, 0);
1852 const b_name = mem.sliceTo(b_decl.name, 0);
1853 return mem.eql(u8, a_name, b_name);
1661 return a_decl.name == b_decl.name;
18541662 }
18551663 };
18561664
......@@ -1862,8 +1670,6 @@ pub const Namespace = struct {
18621670 pub fn destroyDecls(ns: *Namespace, mod: *Module) void {
18631671 const gpa = mod.gpa;
18641672
1865 log.debug("destroyDecls {*}", .{ns});
1866
18671673 var decls = ns.decls;
18681674 ns.decls = .{};
18691675
......@@ -1889,8 +1695,6 @@ pub const Namespace = struct {
18891695 ) !void {
18901696 const gpa = mod.gpa;
18911697
1892 log.debug("deleteAllDecls {*}", .{ns});
1893
18941698 var decls = ns.decls;
18951699 ns.decls = .{};
18961700
......@@ -1919,46 +1723,38 @@ pub const Namespace = struct {
19191723 pub fn renderFullyQualifiedName(
19201724 ns: Namespace,
19211725 mod: *Module,
1922 name: []const u8,
1726 name: InternPool.NullTerminatedString,
19231727 writer: anytype,
19241728 ) @TypeOf(writer).Error!void {
1925 if (ns.parent) |parent| {
1926 const decl_index = ns.getDeclIndex();
1927 const decl = mod.declPtr(decl_index);
1928 try parent.renderFullyQualifiedName(mod, mem.sliceTo(decl.name, 0), writer);
1729 if (ns.parent.unwrap()) |parent| {
1730 const decl = mod.declPtr(ns.getDeclIndex(mod));
1731 try mod.namespacePtr(parent).renderFullyQualifiedName(mod, decl.name, writer);
19291732 } else {
19301733 try ns.file_scope.renderFullyQualifiedName(writer);
19311734 }
1932 if (name.len != 0) {
1933 try writer.writeAll(".");
1934 try writer.writeAll(name);
1935 }
1735 if (name != .empty) try writer.print(".{}", .{name.fmt(&mod.intern_pool)});
19361736 }
19371737
19381738 /// This renders e.g. "std/fs.zig:Dir.OpenOptions"
19391739 pub fn renderFullyQualifiedDebugName(
19401740 ns: Namespace,
19411741 mod: *Module,
1942 name: []const u8,
1742 name: InternPool.NullTerminatedString,
19431743 writer: anytype,
19441744 ) @TypeOf(writer).Error!void {
1945 var separator_char: u8 = '.';
1946 if (ns.parent) |parent| {
1947 const decl_index = ns.getDeclIndex();
1948 const decl = mod.declPtr(decl_index);
1949 try parent.renderFullyQualifiedDebugName(mod, mem.sliceTo(decl.name, 0), writer);
1950 } else {
1745 const separator_char: u8 = if (ns.parent.unwrap()) |parent| sep: {
1746 const decl = mod.declPtr(ns.getDeclIndex(mod));
1747 try mod.namespacePtr(parent).renderFullyQualifiedDebugName(mod, decl.name, writer);
1748 break :sep '.';
1749 } else sep: {
19511750 try ns.file_scope.renderFullyQualifiedDebugName(writer);
1952 separator_char = ':';
1953 }
1954 if (name.len != 0) {
1955 try writer.writeByte(separator_char);
1956 try writer.writeAll(name);
1957 }
1751 break :sep ':';
1752 };
1753 if (name != .empty) try writer.print("{c}{}", .{ separator_char, name.fmt(&mod.intern_pool) });
19581754 }
19591755
1960 pub fn getDeclIndex(ns: Namespace) Decl.Index {
1961 return ns.ty.getOwnerDecl();
1756 pub fn getDeclIndex(ns: Namespace, mod: *Module) Decl.Index {
1757 return ns.ty.getOwnerDecl(mod);
19621758 }
19631759};
19641760
......@@ -2140,11 +1936,11 @@ pub const File = struct {
21401936 };
21411937 }
21421938
2143 pub fn fullyQualifiedNameZ(file: File, gpa: Allocator) ![:0]u8 {
2144 var buf = std.ArrayList(u8).init(gpa);
2145 defer buf.deinit();
2146 try file.renderFullyQualifiedName(buf.writer());
2147 return buf.toOwnedSliceSentinel(0);
1939 pub fn fullyQualifiedName(file: File, mod: *Module) !InternPool.NullTerminatedString {
1940 const ip = &mod.intern_pool;
1941 const start = ip.string_bytes.items.len;
1942 try file.renderFullyQualifiedName(ip.string_bytes.writer(mod.gpa));
1943 return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start);
21481944 }
21491945
21501946 /// Returns the full path to this file relative to its package.
......@@ -2268,7 +2064,7 @@ pub const ErrorMsg = struct {
22682064 reference_trace: []Trace = &.{},
22692065
22702066 pub const Trace = struct {
2271 decl: ?[*:0]const u8,
2067 decl: InternPool.OptionalNullTerminatedString,
22722068 src_loc: SrcLoc,
22732069 hidden: u32 = 0,
22742070 };
......@@ -2281,7 +2077,7 @@ pub const ErrorMsg = struct {
22812077 ) !*ErrorMsg {
22822078 const err_msg = try gpa.create(ErrorMsg);
22832079 errdefer gpa.destroy(err_msg);
2284 err_msg.* = try init(gpa, src_loc, format, args);
2080 err_msg.* = try ErrorMsg.init(gpa, src_loc, format, args);
22852081 return err_msg;
22862082 }
22872083
......@@ -3287,7 +3083,7 @@ pub const LazySrcLoc = union(enum) {
32873083 }
32883084
32893085 /// Upgrade to a `SrcLoc` based on the `Decl` provided.
3290 pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc {
3086 pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl, mod: *Module) SrcLoc {
32913087 return switch (lazy) {
32923088 .unneeded,
32933089 .entire_file,
......@@ -3295,7 +3091,7 @@ pub const LazySrcLoc = union(enum) {
32953091 .token_abs,
32963092 .node_abs,
32973093 => .{
3298 .file_scope = decl.getFileScope(),
3094 .file_scope = decl.getFileScope(mod),
32993095 .parent_decl_node = 0,
33003096 .lazy = lazy,
33013097 },
......@@ -3361,7 +3157,7 @@ pub const LazySrcLoc = union(enum) {
33613157 .for_input,
33623158 .for_capture_from_input,
33633159 => .{
3364 .file_scope = decl.getFileScope(),
3160 .file_scope = decl.getFileScope(mod),
33653161 .parent_decl_node = decl.src_node,
33663162 .lazy = lazy,
33673163 },
......@@ -3391,6 +3187,12 @@ pub const CompileError = error{
33913187 ComptimeBreak,
33923188};
33933189
3190pub fn init(mod: *Module) !void {
3191 const gpa = mod.gpa;
3192 try mod.intern_pool.init(gpa);
3193 try mod.global_error_set.put(gpa, .empty, {});
3194}
3195
33943196pub fn deinit(mod: *Module) void {
33953197 const gpa = mod.gpa;
33963198
......@@ -3489,42 +3291,29 @@ pub fn deinit(mod: *Module) void {
34893291 }
34903292 mod.export_owners.deinit(gpa);
34913293
3492 {
3493 var it = mod.global_error_set.keyIterator();
3494 while (it.next()) |key| {
3495 gpa.free(key.*);
3496 }
3497 mod.global_error_set.deinit(gpa);
3498 }
3294 mod.global_error_set.deinit(gpa);
34993295
3500 mod.error_name_list.deinit(gpa);
35013296 mod.test_functions.deinit(gpa);
35023297 mod.align_stack_fns.deinit(gpa);
35033298 mod.monomorphed_funcs.deinit(gpa);
35043299
3505 {
3506 var it = mod.memoized_calls.iterator();
3507 while (it.next()) |entry| {
3508 gpa.free(entry.key_ptr.args);
3509 entry.value_ptr.arena.promote(gpa).deinit();
3510 }
3511 mod.memoized_calls.deinit(gpa);
3512 }
3513
35143300 mod.decls_free_list.deinit(gpa);
35153301 mod.allocated_decls.deinit(gpa);
35163302 mod.global_assembly.deinit(gpa);
35173303 mod.reference_table.deinit(gpa);
35183304
3519 mod.string_literal_table.deinit(gpa);
3520 mod.string_literal_bytes.deinit(gpa);
3305 mod.namespaces_free_list.deinit(gpa);
3306 mod.allocated_namespaces.deinit(gpa);
3307
3308 mod.memoized_decls.deinit(gpa);
3309 mod.intern_pool.deinit(gpa);
3310 mod.tmp_hack_arena.deinit();
35213311}
35223312
35233313pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
35243314 const gpa = mod.gpa;
35253315 {
35263316 const decl = mod.declPtr(decl_index);
3527 log.debug("destroy {*} ({s})", .{ decl, decl.name });
35283317 _ = mod.test_functions.swapRemove(decl_index);
35293318 if (decl.deletion_flag) {
35303319 assert(mod.deletion_set.swapRemove(decl_index));
......@@ -3533,14 +3322,15 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
35333322 gpa.free(kv.value);
35343323 }
35353324 if (decl.has_tv) {
3536 if (decl.getInnerNamespace()) |namespace| {
3537 namespace.destroyDecls(mod);
3325 if (decl.getOwnedInnerNamespaceIndex(mod).unwrap()) |i| {
3326 mod.namespacePtr(i).destroyDecls(mod);
3327 mod.destroyNamespace(i);
35383328 }
35393329 }
3330 if (decl.src_scope) |scope| scope.decRef(gpa);
35403331 decl.clearValues(mod);
35413332 decl.dependants.deinit(gpa);
35423333 decl.dependencies.deinit(gpa);
3543 decl.clearName(gpa);
35443334 decl.* = undefined;
35453335 }
35463336 mod.decls_free_list.append(gpa, decl_index) catch {
......@@ -3554,24 +3344,55 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void {
35543344 }
35553345}
35563346
3557pub fn declPtr(mod: *Module, decl_index: Decl.Index) *Decl {
3558 return mod.allocated_decls.at(@enumToInt(decl_index));
3347pub fn declPtr(mod: *Module, index: Decl.Index) *Decl {
3348 return mod.allocated_decls.at(@enumToInt(index));
3349}
3350
3351pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace {
3352 return mod.allocated_namespaces.at(@enumToInt(index));
3353}
3354
3355pub fn unionPtr(mod: *Module, index: Union.Index) *Union {
3356 return mod.intern_pool.unionPtr(index);
3357}
3358
3359pub fn structPtr(mod: *Module, index: Struct.Index) *Struct {
3360 return mod.intern_pool.structPtr(index);
3361}
3362
3363pub fn funcPtr(mod: *Module, index: Fn.Index) *Fn {
3364 return mod.intern_pool.funcPtr(index);
3365}
3366
3367pub fn inferredErrorSetPtr(mod: *Module, index: Fn.InferredErrorSet.Index) *Fn.InferredErrorSet {
3368 return mod.intern_pool.inferredErrorSetPtr(index);
3369}
3370
3371pub fn namespacePtrUnwrap(mod: *Module, index: Namespace.OptionalIndex) ?*Namespace {
3372 return mod.namespacePtr(index.unwrap() orelse return null);
3373}
3374
3375/// This one accepts an index from the InternPool and asserts that it is not
3376/// the anonymous empty struct type.
3377pub fn structPtrUnwrap(mod: *Module, index: Struct.OptionalIndex) ?*Struct {
3378 return mod.structPtr(index.unwrap() orelse return null);
3379}
3380
3381pub fn funcPtrUnwrap(mod: *Module, index: Fn.OptionalIndex) ?*Fn {
3382 return mod.funcPtr(index.unwrap() orelse return null);
35593383}
35603384
35613385/// Returns true if and only if the Decl is the top level struct associated with a File.
35623386pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
35633387 const decl = mod.declPtr(decl_index);
3564 if (decl.src_namespace.parent != null)
3388 const namespace = mod.namespacePtr(decl.src_namespace);
3389 if (namespace.parent != .none)
35653390 return false;
3566 return decl_index == decl.src_namespace.getDeclIndex();
3391 return decl_index == namespace.getDeclIndex(mod);
35673392}
35683393
35693394fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void {
3570 for (export_list.items) |exp| {
3571 gpa.free(exp.options.name);
3572 if (exp.options.section) |s| gpa.free(s);
3573 gpa.destroy(exp);
3574 }
3395 for (export_list.items) |exp| gpa.destroy(exp);
35753396 export_list.deinit(gpa);
35763397}
35773398
......@@ -3990,9 +3811,6 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
39903811 if (decl.zir_decl_index != 0) {
39913812 const old_zir_decl_index = decl.zir_decl_index;
39923813 const new_zir_decl_index = extra_map.get(old_zir_decl_index) orelse {
3993 log.debug("updateZirRefs {s}: delete {*} ({s})", .{
3994 file.sub_file_path, decl, decl.name,
3995 });
39963814 try file.deleted_decls.append(gpa, decl_index);
39973815 continue;
39983816 };
......@@ -4000,41 +3818,34 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void {
40003818 decl.zir_decl_index = new_zir_decl_index;
40013819 const new_hash = decl.contentsHashZir(new_zir);
40023820 if (!std.zig.srcHashEql(old_hash, new_hash)) {
4003 log.debug("updateZirRefs {s}: outdated {*} ({s}) {d} => {d}", .{
4004 file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
4005 });
40063821 try file.outdated_decls.append(gpa, decl_index);
4007 } else {
4008 log.debug("updateZirRefs {s}: unchanged {*} ({s}) {d} => {d}", .{
4009 file.sub_file_path, decl, decl.name, old_zir_decl_index, new_zir_decl_index,
4010 });
40113822 }
40123823 }
40133824
40143825 if (!decl.owns_tv) continue;
40153826
4016 if (decl.getStruct()) |struct_obj| {
3827 if (decl.getOwnedStruct(mod)) |struct_obj| {
40173828 struct_obj.zir_index = inst_map.get(struct_obj.zir_index) orelse {
40183829 try file.deleted_decls.append(gpa, decl_index);
40193830 continue;
40203831 };
40213832 }
40223833
4023 if (decl.getUnion()) |union_obj| {
3834 if (decl.getOwnedUnion(mod)) |union_obj| {
40243835 union_obj.zir_index = inst_map.get(union_obj.zir_index) orelse {
40253836 try file.deleted_decls.append(gpa, decl_index);
40263837 continue;
40273838 };
40283839 }
40293840
4030 if (decl.getFunction()) |func| {
3841 if (decl.getOwnedFunction(mod)) |func| {
40313842 func.zir_body_inst = inst_map.get(func.zir_body_inst) orelse {
40323843 try file.deleted_decls.append(gpa, decl_index);
40333844 continue;
40343845 };
40353846 }
40363847
4037 if (decl.getInnerNamespace()) |namespace| {
3848 if (decl.getOwnedInnerNamespace(mod)) |namespace| {
40383849 for (namespace.decls.keys()) |sub_decl| {
40393850 try decl_stack.append(gpa, sub_decl);
40403851 }
......@@ -4207,14 +4018,12 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
42074018 .complete => return,
42084019
42094020 .outdated => blk: {
4210 log.debug("re-analyzing {*} ({s})", .{ decl, decl.name });
4211
42124021 // The exports this Decl performs will be re-discovered, so we remove them here
42134022 // prior to re-analysis.
42144023 try mod.deleteDeclExports(decl_index);
42154024
42164025 // Similarly, `@setAlignStack` invocations will be re-discovered.
4217 if (decl.getFunction()) |func| {
4026 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
42184027 _ = mod.align_stack_fns.remove(func);
42194028 }
42204029
......@@ -4223,9 +4032,6 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
42234032 const dep = mod.declPtr(dep_index);
42244033 dep.removeDependant(decl_index);
42254034 if (dep.dependants.count() == 0 and !dep.deletion_flag) {
4226 log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{
4227 decl, decl.name, dep, dep.name,
4228 });
42294035 try mod.markDeclForDeletion(dep_index);
42304036 }
42314037 }
......@@ -4237,7 +4043,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
42374043 .unreferenced => false,
42384044 };
42394045
4240 var decl_prog_node = mod.sema_prog_node.start(mem.sliceTo(decl.name, 0), 0);
4046 var decl_prog_node = mod.sema_prog_node.start("", 0);
42414047 decl_prog_node.activate();
42424048 defer decl_prog_node.end();
42434049
......@@ -4264,7 +4070,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
42644070 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
42654071 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
42664072 mod.gpa,
4267 decl.srcLoc(),
4073 decl.srcLoc(mod),
42684074 "unable to analyze: {s}",
42694075 .{@errorName(e)},
42704076 ));
......@@ -4277,7 +4083,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
42774083 // Update all dependents which have at least this level of dependency.
42784084 // If our type remained the same and we're a function, only update
42794085 // decls which depend on our body; otherwise, update all dependents.
4280 const update_level: Decl.DepType = if (!type_changed and decl.ty.zigTypeTag() == .Fn) .function_body else .normal;
4086 const update_level: Decl.DepType = if (!type_changed and decl.ty.zigTypeTag(mod) == .Fn) .function_body else .normal;
42814087
42824088 for (decl.dependants.keys(), decl.dependants.values()) |dep_index, dep_type| {
42834089 if (@enumToInt(dep_type) < @enumToInt(update_level)) continue;
......@@ -4304,10 +4110,11 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
43044110 }
43054111}
43064112
4307pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
4113pub fn ensureFuncBodyAnalyzed(mod: *Module, func_index: Fn.Index) SemaError!void {
43084114 const tracy = trace(@src());
43094115 defer tracy.end();
43104116
4117 const func = mod.funcPtr(func_index);
43114118 const decl_index = func.owner_decl;
43124119 const decl = mod.declPtr(decl_index);
43134120
......@@ -4339,7 +4146,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43394146 defer tmp_arena.deinit();
43404147 const sema_arena = tmp_arena.allocator();
43414148
4342 var air = mod.analyzeFnBody(func, sema_arena) catch |err| switch (err) {
4149 var air = mod.analyzeFnBody(func_index, sema_arena) catch |err| switch (err) {
43434150 error.AnalysisFail => {
43444151 if (func.state == .in_progress) {
43454152 // If this decl caused the compile error, the analysis field would
......@@ -4365,17 +4172,14 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43654172
43664173 if (no_bin_file and !dump_air and !dump_llvm_ir) return;
43674174
4368 log.debug("analyze liveness of {s}", .{decl.name});
4369 var liveness = try Liveness.analyze(gpa, air);
4175 var liveness = try Liveness.analyze(gpa, air, &mod.intern_pool);
43704176 defer liveness.deinit(gpa);
43714177
43724178 if (dump_air) {
43734179 const fqn = try decl.getFullyQualifiedName(mod);
4374 defer mod.gpa.free(fqn);
4375
4376 std.debug.print("# Begin Function AIR: {s}:\n", .{fqn});
4180 std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(&mod.intern_pool)});
43774181 @import("print_air.zig").dump(mod, air, liveness);
4378 std.debug.print("# End Function AIR: {s}\n\n", .{fqn});
4182 std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(&mod.intern_pool)});
43794183 }
43804184
43814185 if (std.debug.runtime_safety) {
......@@ -4383,6 +4187,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43834187 .gpa = gpa,
43844188 .air = air,
43854189 .liveness = liveness,
4190 .intern_pool = &mod.intern_pool,
43864191 };
43874192 defer verify.deinit();
43884193
......@@ -4394,7 +4199,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
43944199 decl_index,
43954200 try Module.ErrorMsg.create(
43964201 gpa,
4397 decl.srcLoc(),
4202 decl.srcLoc(mod),
43984203 "invalid liveness: {s}",
43994204 .{@errorName(err)},
44004205 ),
......@@ -4407,7 +4212,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
44074212
44084213 if (no_bin_file and !dump_llvm_ir) return;
44094214
4410 comp.bin_file.updateFunc(mod, func, air, liveness) catch |err| switch (err) {
4215 comp.bin_file.updateFunc(mod, func_index, air, liveness) catch |err| switch (err) {
44114216 error.OutOfMemory => return error.OutOfMemory,
44124217 error.AnalysisFail => {
44134218 decl.analysis = .codegen_failure;
......@@ -4417,7 +4222,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
44174222 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
44184223 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create(
44194224 gpa,
4420 decl.srcLoc(),
4225 decl.srcLoc(mod),
44214226 "unable to codegen: {s}",
44224227 .{@errorName(err)},
44234228 ));
......@@ -4437,7 +4242,8 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void {
44374242/// analyzed, and for ensuring it can exist at runtime (see
44384243/// `sema.fnHasRuntimeBits`). This function does *not* guarantee that the body
44394244/// will be analyzed when it returns: for that, see `ensureFuncBodyAnalyzed`.
4440pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
4245pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func_index: Fn.Index) !void {
4246 const func = mod.funcPtr(func_index);
44414247 const decl_index = func.owner_decl;
44424248 const decl = mod.declPtr(decl_index);
44434249
......@@ -4475,7 +4281,7 @@ pub fn ensureFuncBodyAnalysisQueued(mod: *Module, func: *Fn) !void {
44754281
44764282 // Decl itself is safely analyzed, and body analysis is not yet queued
44774283
4478 try mod.comp.work_queue.writeItem(.{ .codegen_func = func });
4284 try mod.comp.work_queue.writeItem(.{ .codegen_func = func_index });
44794285 if (mod.emit_h != null) {
44804286 // TODO: we ideally only want to do this if the function's type changed
44814287 // since the last update
......@@ -4527,42 +4333,54 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
45274333 if (file.root_decl != .none) return;
45284334
45294335 const gpa = mod.gpa;
4530 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
4531 errdefer new_decl_arena.deinit();
4532 const new_decl_arena_allocator = new_decl_arena.allocator();
4533
4534 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
4535 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
4536 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
4537 const ty_ty = comptime Type.initTag(.type);
4538 struct_obj.* = .{
4539 .owner_decl = undefined, // set below
4336
4337 // Because these three things each reference each other, `undefined`
4338 // placeholders are used before being set after the struct type gains an
4339 // InternPool index.
4340 const new_namespace_index = try mod.createNamespace(.{
4341 .parent = .none,
4342 .ty = undefined,
4343 .file_scope = file,
4344 });
4345 const new_namespace = mod.namespacePtr(new_namespace_index);
4346 errdefer mod.destroyNamespace(new_namespace_index);
4347
4348 const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, null);
4349 const new_decl = mod.declPtr(new_decl_index);
4350 errdefer @panic("TODO error handling");
4351
4352 const struct_index = try mod.createStruct(.{
4353 .owner_decl = new_decl_index,
45404354 .fields = .{},
45414355 .zir_index = undefined, // set below
45424356 .layout = .Auto,
45434357 .status = .none,
45444358 .known_non_opv = undefined,
45454359 .is_tuple = undefined, // set below
4546 .namespace = .{
4547 .parent = null,
4548 .ty = struct_ty,
4549 .file_scope = file,
4550 },
4551 };
4552 const new_decl_index = try mod.allocateNewDecl(&struct_obj.namespace, 0, null);
4553 const new_decl = mod.declPtr(new_decl_index);
4360 .namespace = new_namespace_index,
4361 });
4362 errdefer mod.destroyStruct(struct_index);
4363
4364 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
4365 .index = struct_index.toOptional(),
4366 .namespace = new_namespace_index.toOptional(),
4367 } });
4368 // TODO: figure out InternPool removals for incremental compilation
4369 //errdefer mod.intern_pool.remove(struct_ty);
4370
4371 new_namespace.ty = struct_ty.toType();
45544372 file.root_decl = new_decl_index.toOptional();
4555 struct_obj.owner_decl = new_decl_index;
4556 new_decl.name = try file.fullyQualifiedNameZ(gpa);
4373
4374 new_decl.name = try file.fullyQualifiedName(mod);
45574375 new_decl.src_line = 0;
45584376 new_decl.is_pub = true;
45594377 new_decl.is_exported = false;
45604378 new_decl.has_align = false;
45614379 new_decl.has_linksection_or_addrspace = false;
4562 new_decl.ty = ty_ty;
4563 new_decl.val = struct_val;
4380 new_decl.ty = Type.type;
4381 new_decl.val = struct_ty.toValue();
45644382 new_decl.@"align" = 0;
4565 new_decl.@"linksection" = null;
4383 new_decl.@"linksection" = .none;
45664384 new_decl.has_tv = true;
45674385 new_decl.owns_tv = true;
45684386 new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive.
......@@ -4573,6 +4391,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
45734391 if (file.status == .success_zir) {
45744392 assert(file.zir_loaded);
45754393 const main_struct_inst = Zir.main_struct_inst;
4394 const struct_obj = mod.structPtr(struct_index);
45764395 struct_obj.zir_index = main_struct_inst;
45774396 const extended = file.zir.instructions.items(.data)[main_struct_inst].extended;
45784397 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -4582,25 +4401,34 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
45824401 defer sema_arena.deinit();
45834402 const sema_arena_allocator = sema_arena.allocator();
45844403
4404 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
4405 defer comptime_mutable_decls.deinit();
4406
45854407 var sema: Sema = .{
45864408 .mod = mod,
45874409 .gpa = gpa,
45884410 .arena = sema_arena_allocator,
4589 .perm_arena = new_decl_arena_allocator,
45904411 .code = file.zir,
45914412 .owner_decl = new_decl,
45924413 .owner_decl_index = new_decl_index,
45934414 .func = null,
4415 .func_index = .none,
45944416 .fn_ret_ty = Type.void,
45954417 .owner_func = null,
4418 .owner_func_index = .none,
4419 .comptime_mutable_decls = &comptime_mutable_decls,
45964420 };
45974421 defer sema.deinit();
45984422
4599 var wip_captures = try WipCaptureScope.init(gpa, new_decl_arena_allocator, null);
4423 var wip_captures = try WipCaptureScope.init(gpa, null);
46004424 defer wip_captures.deinit();
46014425
4602 if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_obj)) |_| {
4426 if (sema.analyzeStructDecl(new_decl, main_struct_inst, struct_index)) |_| {
46034427 try wip_captures.finalize();
4428 for (comptime_mutable_decls.items) |decl_index| {
4429 const decl = mod.declPtr(decl_index);
4430 try decl.intern(mod);
4431 }
46044432 new_decl.analysis = .complete;
46054433 } else |err| switch (err) {
46064434 error.OutOfMemory => return error.OutOfMemory,
......@@ -4632,8 +4460,6 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
46324460 } else {
46334461 new_decl.analysis = .file_failure;
46344462 }
4635
4636 try new_decl.finalizeNewArena(&new_decl_arena);
46374463}
46384464
46394465/// Returns `true` if the Decl type changed.
......@@ -4645,68 +4471,52 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
46454471
46464472 const decl = mod.declPtr(decl_index);
46474473
4648 if (decl.getFileScope().status != .success_zir) {
4474 if (decl.getFileScope(mod).status != .success_zir) {
46494475 return error.AnalysisFail;
46504476 }
46514477
46524478 const gpa = mod.gpa;
4653 const zir = decl.getFileScope().zir;
4479 const zir = decl.getFileScope(mod).zir;
46544480 const zir_datas = zir.instructions.items(.data);
46554481
46564482 decl.analysis = .in_progress;
46574483
4658 // We need the memory for the Type to go into the arena for the Decl
4659 var decl_arena = std.heap.ArenaAllocator.init(gpa);
4660 const decl_arena_allocator = decl_arena.allocator();
4661 const decl_value_arena = blk: {
4662 errdefer decl_arena.deinit();
4663 const s = try decl_arena_allocator.create(ValueArena);
4664 s.* = .{ .state = undefined };
4665 break :blk s;
4666 };
4667 defer {
4668 if (decl.value_arena) |value_arena| {
4669 assert(value_arena.state_acquired == null);
4670 decl_value_arena.prev = value_arena;
4671 }
4672
4673 decl_value_arena.state = decl_arena.state;
4674 decl.value_arena = decl_value_arena;
4675 }
4676
46774484 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
46784485 defer analysis_arena.deinit();
4679 const analysis_arena_allocator = analysis_arena.allocator();
4486
4487 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
4488 defer comptime_mutable_decls.deinit();
46804489
46814490 var sema: Sema = .{
46824491 .mod = mod,
46834492 .gpa = gpa,
4684 .arena = analysis_arena_allocator,
4685 .perm_arena = decl_arena_allocator,
4493 .arena = analysis_arena.allocator(),
46864494 .code = zir,
46874495 .owner_decl = decl,
46884496 .owner_decl_index = decl_index,
46894497 .func = null,
4498 .func_index = .none,
46904499 .fn_ret_ty = Type.void,
46914500 .owner_func = null,
4501 .owner_func_index = .none,
4502 .comptime_mutable_decls = &comptime_mutable_decls,
46924503 };
46934504 defer sema.deinit();
46944505
46954506 if (mod.declIsRoot(decl_index)) {
4696 log.debug("semaDecl root {*} ({s})", .{ decl, decl.name });
46974507 const main_struct_inst = Zir.main_struct_inst;
4698 const struct_obj = decl.getStruct().?;
4508 const struct_index = decl.getOwnedStructIndex(mod).unwrap().?;
4509 const struct_obj = mod.structPtr(struct_index);
46994510 // This might not have gotten set in `semaFile` if the first time had
47004511 // a ZIR failure, so we set it here in case.
47014512 struct_obj.zir_index = main_struct_inst;
4702 try sema.analyzeStructDecl(decl, main_struct_inst, struct_obj);
4513 try sema.analyzeStructDecl(decl, main_struct_inst, struct_index);
47034514 decl.analysis = .complete;
47044515 decl.generation = mod.generation;
47054516 return false;
47064517 }
4707 log.debug("semaDecl {*} ({s})", .{ decl, decl.name });
47084518
4709 var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
4519 var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope);
47104520 defer wip_captures.deinit();
47114521
47124522 var block_scope: Sema.Block = .{
......@@ -4724,12 +4534,16 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47244534 block_scope.params.deinit(gpa);
47254535 }
47264536
4727 const zir_block_index = decl.zirBlockIndex();
4537 const zir_block_index = decl.zirBlockIndex(mod);
47284538 const inst_data = zir_datas[zir_block_index].pl_node;
47294539 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
47304540 const body = zir.extra[extra.end..][0..extra.data.body_len];
47314541 const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
47324542 try wip_captures.finalize();
4543 for (comptime_mutable_decls.items) |ct_decl_index| {
4544 const ct_decl = mod.declPtr(ct_decl_index);
4545 try ct_decl.intern(mod);
4546 }
47334547 const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 };
47344548 const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 };
47354549 const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
......@@ -4748,16 +4562,15 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47484562 decl_tv.ty.fmt(mod),
47494563 });
47504564 }
4751 var buffer: Value.ToTypeBuffer = undefined;
4752 const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator);
4753 if (ty.getNamespace() == null) {
4565 const ty = decl_tv.val.toType();
4566 if (ty.getNamespace(mod) == null) {
47544567 return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});
47554568 }
47564569
4757 decl.ty = Type.type;
4758 decl.val = try Value.Tag.ty.create(decl_arena_allocator, ty);
4570 decl.ty = InternPool.Index.type_type.toType();
4571 decl.val = ty.toValue();
47594572 decl.@"align" = 0;
4760 decl.@"linksection" = null;
4573 decl.@"linksection" = .none;
47614574 decl.has_tv = true;
47624575 decl.owns_tv = false;
47634576 decl.analysis = .complete;
......@@ -4766,8 +4579,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47664579 return true;
47674580 }
47684581
4769 if (decl_tv.val.castTag(.function)) |fn_payload| {
4770 const func = fn_payload.data;
4582 if (mod.intern_pool.indexToFunc(decl_tv.val.toIntern()).unwrap()) |func_index| {
4583 const func = mod.funcPtr(func_index);
47714584 const owns_tv = func.owner_decl == decl_index;
47724585 if (owns_tv) {
47734586 var prev_type_has_bits = false;
......@@ -4775,31 +4588,30 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
47754588 var type_changed = true;
47764589
47774590 if (decl.has_tv) {
4778 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits();
4591 prev_type_has_bits = decl.ty.isFnOrHasRuntimeBits(mod);
47794592 type_changed = !decl.ty.eql(decl_tv.ty, mod);
4780 if (decl.getFunction()) |prev_func| {
4593 if (decl.getOwnedFunction(mod)) |prev_func| {
47814594 prev_is_inline = prev_func.state == .inline_only;
47824595 }
47834596 }
47844597 decl.clearValues(mod);
47854598
4786 decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
4787 decl.val = try decl_tv.val.copy(decl_arena_allocator);
4599 decl.ty = decl_tv.ty;
4600 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
47884601 // linksection, align, and addrspace were already set by Sema
47894602 decl.has_tv = true;
47904603 decl.owns_tv = owns_tv;
47914604 decl.analysis = .complete;
47924605 decl.generation = mod.generation;
47934606
4794 const is_inline = decl.ty.fnCallingConvention() == .Inline;
4607 const is_inline = decl.ty.fnCallingConvention(mod) == .Inline;
47954608 if (decl.is_exported) {
47964609 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
47974610 if (is_inline) {
47984611 return sema.fail(&block_scope, export_src, "export of inline function", .{});
47994612 }
48004613 // The scope needs to have the decl in it.
4801 const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };
4802 try sema.analyzeExport(&block_scope, export_src, options, decl_index);
4614 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
48034615 }
48044616 return type_changed or is_inline != prev_is_inline;
48054617 }
......@@ -4813,64 +4625,57 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
48134625 decl.owns_tv = false;
48144626 var queue_linker_work = false;
48154627 var is_extern = false;
4816 switch (decl_tv.val.tag()) {
4817 .variable => {
4818 const variable = decl_tv.val.castTag(.variable).?.data;
4819 if (variable.owner_decl == decl_index) {
4820 decl.owns_tv = true;
4821 queue_linker_work = true;
4822
4823 const copied_init = try variable.init.copy(decl_arena_allocator);
4824 variable.init = copied_init;
4825 }
4826 },
4827 .extern_fn => {
4828 const extern_fn = decl_tv.val.castTag(.extern_fn).?.data;
4829 if (extern_fn.owner_decl == decl_index) {
4830 decl.owns_tv = true;
4831 queue_linker_work = true;
4832 is_extern = true;
4833 }
4834 },
4835
4628 switch (decl_tv.val.toIntern()) {
48364629 .generic_poison => unreachable,
48374630 .unreachable_value => unreachable,
4631 else => switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
4632 .variable => |variable| if (variable.decl == decl_index) {
4633 decl.owns_tv = true;
4634 queue_linker_work = true;
4635 },
48384636
4839 .function => {},
4637 .extern_func => |extern_fn| if (extern_fn.decl == decl_index) {
4638 decl.owns_tv = true;
4639 queue_linker_work = true;
4640 is_extern = true;
4641 },
48404642
4841 else => {
4842 log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name });
4843 queue_linker_work = true;
4643 .func => {},
4644
4645 else => {
4646 queue_linker_work = true;
4647 },
48444648 },
48454649 }
48464650
4847 decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
4848 decl.val = try decl_tv.val.copy(decl_arena_allocator);
4651 decl.ty = decl_tv.ty;
4652 decl.val = (try decl_tv.val.intern(decl_tv.ty, mod)).toValue();
48494653 decl.@"align" = blk: {
4850 const align_ref = decl.zirAlignRef();
4654 const align_ref = decl.zirAlignRef(mod);
48514655 if (align_ref == .none) break :blk 0;
48524656 break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);
48534657 };
48544658 decl.@"linksection" = blk: {
4855 const linksection_ref = decl.zirLinksectionRef();
4856 if (linksection_ref == .none) break :blk null;
4659 const linksection_ref = decl.zirLinksectionRef(mod);
4660 if (linksection_ref == .none) break :blk .none;
48574661 const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known");
48584662 if (mem.indexOfScalar(u8, bytes, 0) != null) {
48594663 return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
48604664 } else if (bytes.len == 0) {
48614665 return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
48624666 }
4863 break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
4667 const section = try mod.intern_pool.getOrPutString(gpa, bytes);
4668 break :blk section.toOptional();
48644669 };
48654670 decl.@"addrspace" = blk: {
4866 const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) {
4867 .function, .extern_fn => .function,
4671 const addrspace_ctx: Sema.AddressSpaceContext = switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) {
48684672 .variable => .variable,
4673 .extern_func, .func => .function,
48694674 else => .constant,
48704675 };
48714676
48724677 const target = sema.mod.getTarget();
4873 break :blk switch (decl.zirAddrspaceRef()) {
4678 break :blk switch (decl.zirAddrspaceRef(mod)) {
48744679 .none => switch (addrspace_ctx) {
48754680 .function => target_util.defaultAddressSpace(target, .function),
48764681 .variable => target_util.defaultAddressSpace(target, .global_mutable),
......@@ -4888,7 +4693,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
48884693 (queue_linker_work and try sema.typeHasRuntimeBits(decl.ty));
48894694
48904695 if (has_runtime_bits) {
4891 log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });
48924696
48934697 // Needed for codegen_decl which will call updateDecl and then the
48944698 // codegen backend wants full access to the Decl Type.
......@@ -4904,8 +4708,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
49044708 if (decl.is_exported) {
49054709 const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
49064710 // The scope needs to have the decl in it.
4907 const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };
4908 try sema.analyzeExport(&block_scope, export_src, options, decl_index);
4711 try sema.analyzeExport(&block_scope, export_src, .{ .name = decl.name }, decl_index);
49094712 }
49104713
49114714 return type_changed;
......@@ -4930,10 +4733,6 @@ pub fn declareDeclDependencyType(mod: *Module, depender_index: Decl.Index, depen
49304733 }
49314734 }
49324735
4933 log.debug("{*} ({s}) depends on {*} ({s})", .{
4934 depender, depender.name, dependee, dependee.name,
4935 });
4936
49374736 if (dependee.deletion_flag) {
49384737 dependee.deletion_flag = false;
49394738 assert(mod.deletion_set.swapRemove(dependee_index));
......@@ -5222,7 +5021,7 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void {
52225021
52235022pub fn scanNamespace(
52245023 mod: *Module,
5225 namespace: *Namespace,
5024 namespace_index: Namespace.Index,
52265025 extra_start: usize,
52275026 decls_len: u32,
52285027 parent_decl: *Decl,
......@@ -5231,6 +5030,7 @@ pub fn scanNamespace(
52315030 defer tracy.end();
52325031
52335032 const gpa = mod.gpa;
5033 const namespace = mod.namespacePtr(namespace_index);
52345034 const zir = namespace.file_scope.zir;
52355035
52365036 try mod.comp.work_queue.ensureUnusedCapacity(decls_len);
......@@ -5243,7 +5043,7 @@ pub fn scanNamespace(
52435043 var decl_i: u32 = 0;
52445044 var scan_decl_iter: ScanDeclIter = .{
52455045 .module = mod,
5246 .namespace = namespace,
5046 .namespace_index = namespace_index,
52475047 .parent_decl = parent_decl,
52485048 };
52495049 while (decl_i < decls_len) : (decl_i += 1) {
......@@ -5266,7 +5066,7 @@ pub fn scanNamespace(
52665066
52675067const ScanDeclIter = struct {
52685068 module: *Module,
5269 namespace: *Namespace,
5069 namespace_index: Namespace.Index,
52705070 parent_decl: *Decl,
52715071 usingnamespace_index: usize = 0,
52725072 comptime_index: usize = 0,
......@@ -5278,9 +5078,11 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
52785078 defer tracy.end();
52795079
52805080 const mod = iter.module;
5281 const namespace = iter.namespace;
5081 const namespace_index = iter.namespace_index;
5082 const namespace = mod.namespacePtr(namespace_index);
52825083 const gpa = mod.gpa;
52835084 const zir = namespace.file_scope.zir;
5085 const ip = &mod.intern_pool;
52845086
52855087 // zig fmt: off
52865088 const is_pub = (flags & 0b0001) != 0;
......@@ -5300,31 +5102,31 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53005102 // Every Decl needs a name.
53015103 var is_named_test = false;
53025104 var kind: Decl.Kind = .named;
5303 const decl_name: [:0]const u8 = switch (decl_name_index) {
5105 const decl_name: InternPool.NullTerminatedString = switch (decl_name_index) {
53045106 0 => name: {
53055107 if (export_bit) {
53065108 const i = iter.usingnamespace_index;
53075109 iter.usingnamespace_index += 1;
53085110 kind = .@"usingnamespace";
5309 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace_{d}", .{i});
5111 break :name try ip.getOrPutStringFmt(gpa, "usingnamespace_{d}", .{i});
53105112 } else {
53115113 const i = iter.comptime_index;
53125114 iter.comptime_index += 1;
53135115 kind = .@"comptime";
5314 break :name try std.fmt.allocPrintZ(gpa, "comptime_{d}", .{i});
5116 break :name try ip.getOrPutStringFmt(gpa, "comptime_{d}", .{i});
53155117 }
53165118 },
53175119 1 => name: {
53185120 const i = iter.unnamed_test_index;
53195121 iter.unnamed_test_index += 1;
53205122 kind = .@"test";
5321 break :name try std.fmt.allocPrintZ(gpa, "test_{d}", .{i});
5123 break :name try ip.getOrPutStringFmt(gpa, "test_{d}", .{i});
53225124 },
53235125 2 => name: {
53245126 is_named_test = true;
53255127 const test_name = zir.nullTerminatedString(decl_doccomment_index);
53265128 kind = .@"test";
5327 break :name try std.fmt.allocPrintZ(gpa, "decltest.{s}", .{test_name});
5129 break :name try ip.getOrPutStringFmt(gpa, "decltest.{s}", .{test_name});
53285130 },
53295131 else => name: {
53305132 const raw_name = zir.nullTerminatedString(decl_name_index);
......@@ -5332,14 +5134,12 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53325134 is_named_test = true;
53335135 const test_name = zir.nullTerminatedString(decl_name_index + 1);
53345136 kind = .@"test";
5335 break :name try std.fmt.allocPrintZ(gpa, "test.{s}", .{test_name});
5137 break :name try ip.getOrPutStringFmt(gpa, "test.{s}", .{test_name});
53365138 } else {
5337 break :name try gpa.dupeZ(u8, raw_name);
5139 break :name try ip.getOrPutString(gpa, raw_name);
53385140 }
53395141 },
53405142 };
5341 var must_free_decl_name = true;
5342 defer if (must_free_decl_name) gpa.free(decl_name);
53435143
53445144 const is_exported = export_bit and decl_name_index != 0;
53455145 if (kind == .@"usingnamespace") try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1);
......@@ -5347,21 +5147,19 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53475147 // We create a Decl for it regardless of analysis status.
53485148 const gop = try namespace.decls.getOrPutContextAdapted(
53495149 gpa,
5350 @as([]const u8, mem.sliceTo(decl_name, 0)),
5150 decl_name,
53515151 DeclAdapter{ .mod = mod },
53525152 Namespace.DeclContext{ .module = mod },
53535153 );
53545154 const comp = mod.comp;
53555155 if (!gop.found_existing) {
5356 const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope);
5156 const new_decl_index = try mod.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope);
53575157 const new_decl = mod.declPtr(new_decl_index);
53585158 new_decl.kind = kind;
53595159 new_decl.name = decl_name;
5360 must_free_decl_name = false;
53615160 if (kind == .@"usingnamespace") {
53625161 namespace.usingnamespace_set.putAssumeCapacity(new_decl_index, is_pub);
53635162 }
5364 log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace });
53655163 new_decl.src_line = line;
53665164 gop.key_ptr.* = new_decl_index;
53675165 // Exported decls, comptime decls, usingnamespace decls, and
......@@ -5382,7 +5180,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
53825180 if (!comp.bin_file.options.is_test) break :blk false;
53835181 if (decl_pkg != mod.main_pkg) break :blk false;
53845182 if (comp.test_filter) |test_filter| {
5385 if (mem.indexOf(u8, decl_name, test_filter) == null) {
5183 if (mem.indexOf(u8, ip.stringToSlice(decl_name), test_filter) == null) {
53865184 break :blk false;
53875185 }
53885186 }
......@@ -5405,16 +5203,13 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
54055203 const decl = mod.declPtr(decl_index);
54065204 if (kind == .@"test") {
54075205 const src_loc = SrcLoc{
5408 .file_scope = decl.getFileScope(),
5206 .file_scope = decl.getFileScope(mod),
54095207 .parent_decl_node = decl.src_node,
54105208 .lazy = .{ .token_offset = 1 },
54115209 };
5412 const msg = try ErrorMsg.create(
5413 gpa,
5414 src_loc,
5415 "duplicate test name: {s}",
5416 .{decl_name},
5417 );
5210 const msg = try ErrorMsg.create(gpa, src_loc, "duplicate test name: {}", .{
5211 decl_name.fmt(&mod.intern_pool),
5212 });
54185213 errdefer msg.destroy(gpa);
54195214 try mod.failed_decls.putNoClobber(gpa, decl_index, msg);
54205215 const other_src_loc = SrcLoc{
......@@ -5424,7 +5219,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
54245219 };
54255220 try mod.errNoteNonLazy(other_src_loc, msg, "other test here", .{});
54265221 }
5427 log.debug("scan existing {*} ({s}) of {*}", .{ decl, decl.name, namespace });
54285222 // Update the AST node of the decl; even if its contents are unchanged, it may
54295223 // have been re-ordered.
54305224 decl.src_node = decl_node;
......@@ -5436,7 +5230,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
54365230 decl.has_align = has_align;
54375231 decl.has_linksection_or_addrspace = has_linksection_or_addrspace;
54385232 decl.zir_decl_index = @intCast(u32, decl_sub_index);
5439 if (decl.getFunction()) |_| {
5233 if (decl.getOwnedFunctionIndex(mod) != .none) {
54405234 switch (comp.bin_file.tag) {
54415235 .coff, .elf, .macho, .plan9 => {
54425236 // TODO Look into detecting when this would be unnecessary by storing enough state
......@@ -5458,7 +5252,6 @@ pub fn clearDecl(
54585252 defer tracy.end();
54595253
54605254 const decl = mod.declPtr(decl_index);
5461 log.debug("clearing {*} ({s})", .{ decl, decl.name });
54625255
54635256 const gpa = mod.gpa;
54645257 try mod.deletion_set.ensureUnusedCapacity(gpa, decl.dependencies.count());
......@@ -5473,9 +5266,6 @@ pub fn clearDecl(
54735266 const dep = mod.declPtr(dep_index);
54745267 dep.removeDependant(decl_index);
54755268 if (dep.dependants.count() == 0 and !dep.deletion_flag) {
5476 log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{
5477 decl, decl.name, dep, dep.name,
5478 });
54795269 // We don't recursively perform a deletion here, because during the update,
54805270 // another reference to it may turn up.
54815271 dep.deletion_flag = true;
......@@ -5510,10 +5300,10 @@ pub fn clearDecl(
55105300 try mod.deleteDeclExports(decl_index);
55115301
55125302 if (decl.has_tv) {
5513 if (decl.ty.isFnOrHasRuntimeBits()) {
5303 if (decl.ty.isFnOrHasRuntimeBits(mod)) {
55145304 mod.comp.bin_file.freeDecl(decl_index);
55155305 }
5516 if (decl.getInnerNamespace()) |namespace| {
5306 if (decl.getOwnedInnerNamespace(mod)) |namespace| {
55175307 try namespace.deleteAllDecls(mod, outdated_decls);
55185308 }
55195309 }
......@@ -5530,10 +5320,9 @@ pub fn clearDecl(
55305320/// This function is exclusively called for anonymous decls.
55315321pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void {
55325322 const decl = mod.declPtr(decl_index);
5533 log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name });
55345323
55355324 assert(!mod.declIsRoot(decl_index));
5536 assert(decl.src_namespace.anon_decls.swapRemove(decl_index));
5325 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
55375326
55385327 const dependants = decl.dependants.keys();
55395328 for (dependants) |dep| {
......@@ -5558,10 +5347,9 @@ fn markDeclForDeletion(mod: *Module, decl_index: Decl.Index) !void {
55585347/// If other decls depend on this decl, they must be aborted first.
55595348pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
55605349 const decl = mod.declPtr(decl_index);
5561 log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name });
55625350
55635351 assert(!mod.declIsRoot(decl_index));
5564 assert(decl.src_namespace.anon_decls.swapRemove(decl_index));
5352 assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index));
55655353
55665354 // An aborted decl must not have dependants -- they must have
55675355 // been aborted first and removed from this list.
......@@ -5575,6 +5363,17 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
55755363 mod.destroyDecl(decl_index);
55765364}
55775365
5366/// Finalize the creation of an anon decl.
5367pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
5368 // The Decl starts off with alive=false and the codegen backend will set alive=true
5369 // if the Decl is referenced by an instruction or another constant. Otherwise,
5370 // the Decl will be garbage collected by the `codegen_decl` task instead of sent
5371 // to the linker.
5372 if (mod.declPtr(decl_index).ty.isFnOrHasRuntimeBits(mod)) {
5373 try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = decl_index });
5374 }
5375}
5376
55785377/// Delete all the Export objects that are caused by this Decl. Re-analysis of
55795378/// this Decl will cause them to be re-created (or not).
55805379fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
......@@ -5600,51 +5399,53 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void
56005399 }
56015400 }
56025401 if (mod.comp.bin_file.cast(link.File.Elf)) |elf| {
5603 elf.deleteDeclExport(decl_index, exp.options.name);
5402 elf.deleteDeclExport(decl_index, exp.opts.name);
56045403 }
56055404 if (mod.comp.bin_file.cast(link.File.MachO)) |macho| {
5606 try macho.deleteDeclExport(decl_index, exp.options.name);
5405 try macho.deleteDeclExport(decl_index, exp.opts.name);
56075406 }
56085407 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
56095408 wasm.deleteDeclExport(decl_index);
56105409 }
56115410 if (mod.comp.bin_file.cast(link.File.Coff)) |coff| {
5612 coff.deleteDeclExport(decl_index, exp.options.name);
5411 coff.deleteDeclExport(decl_index, exp.opts.name);
56135412 }
56145413 if (mod.failed_exports.fetchSwapRemove(exp)) |failed_kv| {
56155414 failed_kv.value.destroy(mod.gpa);
56165415 }
5617 mod.gpa.free(exp.options.name);
56185416 mod.gpa.destroy(exp);
56195417 }
56205418 export_owners.deinit(mod.gpa);
56215419}
56225420
5623pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
5421pub fn analyzeFnBody(mod: *Module, func_index: Fn.Index, arena: Allocator) SemaError!Air {
56245422 const tracy = trace(@src());
56255423 defer tracy.end();
56265424
56275425 const gpa = mod.gpa;
5426 const func = mod.funcPtr(func_index);
56285427 const decl_index = func.owner_decl;
56295428 const decl = mod.declPtr(decl_index);
56305429
5631 // Use the Decl's arena for captured values.
5632 var decl_arena: std.heap.ArenaAllocator = undefined;
5633 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
5634 defer decl.value_arena.?.release(&decl_arena);
5430 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
5431 defer comptime_mutable_decls.deinit();
5432
5433 const fn_ty = decl.ty;
56355434
56365435 var sema: Sema = .{
56375436 .mod = mod,
56385437 .gpa = gpa,
56395438 .arena = arena,
5640 .perm_arena = decl_arena_allocator,
5641 .code = decl.getFileScope().zir,
5439 .code = decl.getFileScope(mod).zir,
56425440 .owner_decl = decl,
56435441 .owner_decl_index = decl_index,
56445442 .func = func,
5645 .fn_ret_ty = decl.ty.fnReturnType(),
5443 .func_index = func_index.toOptional(),
5444 .fn_ret_ty = mod.typeToFunc(fn_ty).?.return_type.toType(),
56465445 .owner_func = func,
5446 .owner_func_index = func_index.toOptional(),
56475447 .branch_quota = @max(func.branch_quota, Sema.default_branch_quota),
5448 .comptime_mutable_decls = &comptime_mutable_decls,
56485449 };
56495450 defer sema.deinit();
56505451
......@@ -5656,7 +5457,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56565457 try sema.air_extra.ensureTotalCapacity(gpa, reserved_count);
56575458 sema.air_extra.items.len += reserved_count;
56585459
5659 var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
5460 var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope);
56605461 defer wip_captures.deinit();
56615462
56625463 var inner_block: Sema.Block = .{
......@@ -5680,9 +5481,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56805481 // This could be a generic function instantiation, however, in which case we need to
56815482 // map the comptime parameters to constant values and only emit arg AIR instructions
56825483 // for the runtime ones.
5683 const fn_ty = decl.ty;
5684 const fn_ty_info = fn_ty.fnInfo();
5685 const runtime_params_len = @intCast(u32, fn_ty_info.param_types.len);
5484 const runtime_params_len = @intCast(u32, mod.typeToFunc(fn_ty).?.param_types.len);
56865485 try inner_block.instructions.ensureTotalCapacityPrecise(gpa, runtime_params_len);
56875486 try sema.air_instructions.ensureUnusedCapacity(gpa, fn_info.total_params_len * 2); // * 2 for the `addType`
56885487 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_info.param_body);
......@@ -5697,9 +5496,9 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
56975496 const param_ty = if (func.comptime_args) |comptime_args| t: {
56985497 const arg_tv = comptime_args[total_param_index];
56995498
5700 const arg_val = if (arg_tv.val.tag() != .generic_poison)
5499 const arg_val = if (!arg_tv.val.isGenericPoison())
57015500 arg_tv.val
5702 else if (arg_tv.ty.onePossibleValue()) |opv|
5501 else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
57035502 opv
57045503 else
57055504 break :t arg_tv.ty;
......@@ -5708,7 +5507,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
57085507 sema.inst_map.putAssumeCapacityNoClobber(inst, arg);
57095508 total_param_index += 1;
57105509 continue;
5711 } else fn_ty_info.param_types[runtime_param_index];
5510 } else mod.typeToFunc(fn_ty).?.param_types[runtime_param_index].toType();
57125511
57135512 const opt_opv = sema.typeHasOnePossibleValue(param_ty) catch |err| switch (err) {
57145513 error.NeededSourceLocation => unreachable,
......@@ -5740,7 +5539,6 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
57405539 }
57415540
57425541 func.state = .in_progress;
5743 log.debug("set {s} to in_progress", .{decl.name});
57445542
57455543 const last_arg_index = inner_block.instructions.items.len;
57465544
......@@ -5765,7 +5563,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
57655563 // is unused so it just has to be a no-op.
57665564 sema.air_instructions.set(ptr_inst.*, .{
57675565 .tag = .alloc,
5768 .data = .{ .ty = Type.initTag(.single_const_pointer_to_comptime_int) },
5566 .data = .{ .ty = Type.single_const_pointer_to_comptime_int },
57695567 });
57705568 }
57715569 }
......@@ -5773,7 +5571,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
57735571 // If we don't get an error return trace from a caller, create our own.
57745572 if (func.calls_or_awaits_errorable_fn and
57755573 mod.comp.bin_file.options.error_return_tracing and
5776 !sema.fn_ret_ty.isError())
5574 !sema.fn_ret_ty.isError(mod))
57775575 {
57785576 sema.setupErrorReturnTrace(&inner_block, last_arg_index) catch |err| switch (err) {
57795577 // TODO make these unreachable instead of @panic
......@@ -5786,6 +5584,10 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
57865584 }
57875585
57885586 try wip_captures.finalize();
5587 for (comptime_mutable_decls.items) |ct_decl_index| {
5588 const ct_decl = mod.declPtr(ct_decl_index);
5589 try ct_decl.intern(mod);
5590 }
57895591
57905592 // Copy the block into place and mark that as the main block.
57915593 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len +
......@@ -5797,14 +5599,13 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
57975599 sema.air_extra.items[@enumToInt(Air.ExtraIndex.main_block)] = main_block_index;
57985600
57995601 func.state = .success;
5800 log.debug("set {s} to success", .{decl.name});
58015602
58025603 // Finally we must resolve the return type and parameter types so that backends
58035604 // have full access to type information.
58045605 // Crucially, this happens *after* we set the function state to success above,
58055606 // so that dependencies on the function body will now be satisfied rather than
58065607 // result in circular dependency errors.
5807 sema.resolveFnTypes(fn_ty_info) catch |err| switch (err) {
5608 sema.resolveFnTypes(fn_ty) catch |err| switch (err) {
58085609 error.NeededSourceLocation => unreachable,
58095610 error.GenericPoison => unreachable,
58105611 error.ComptimeReturn => unreachable,
......@@ -5820,9 +5621,8 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
58205621
58215622 // Similarly, resolve any queued up types that were requested to be resolved for
58225623 // the backends.
5823 for (sema.types_to_resolve.items) |inst_ref| {
5824 const ty = sema.getTmpAir().getRefType(inst_ref);
5825 sema.resolveTypeFully(ty) catch |err| switch (err) {
5624 for (sema.types_to_resolve.keys()) |ty| {
5625 sema.resolveTypeFully(ty.toType()) catch |err| switch (err) {
58265626 error.NeededSourceLocation => unreachable,
58275627 error.GenericPoison => unreachable,
58285628 error.ComptimeReturn => unreachable,
......@@ -5840,13 +5640,11 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
58405640 return Air{
58415641 .instructions = sema.air_instructions.toOwnedSlice(),
58425642 .extra = try sema.air_extra.toOwnedSlice(gpa),
5843 .values = try sema.air_values.toOwnedSlice(gpa),
58445643 };
58455644}
58465645
58475646fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
58485647 const decl = mod.declPtr(decl_index);
5849 log.debug("mark outdated {*} ({s})", .{ decl, decl.name });
58505648 try mod.comp.work_queue.writeItem(.{ .analyze_decl = decl_index });
58515649 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
58525650 kv.value.destroy(mod.gpa);
......@@ -5854,11 +5652,8 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
58545652 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
58555653 for (kv.value) |err| err.deinit(mod.gpa);
58565654 }
5857 if (decl.has_tv and decl.owns_tv) {
5858 if (decl.val.castTag(.function)) |payload| {
5859 const func = payload.data;
5860 _ = mod.align_stack_fns.remove(func);
5861 }
5655 if (decl.getOwnedFunctionIndex(mod).unwrap()) |func| {
5656 _ = mod.align_stack_fns.remove(func);
58625657 }
58635658 if (mod.emit_h) |emit_h| {
58645659 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
......@@ -5869,9 +5664,51 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
58695664 decl.analysis = .outdated;
58705665}
58715666
5667pub fn createNamespace(mod: *Module, initialization: Namespace) !Namespace.Index {
5668 if (mod.namespaces_free_list.popOrNull()) |index| {
5669 mod.allocated_namespaces.at(@enumToInt(index)).* = initialization;
5670 return index;
5671 }
5672 const ptr = try mod.allocated_namespaces.addOne(mod.gpa);
5673 ptr.* = initialization;
5674 return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1);
5675}
5676
5677pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void {
5678 mod.namespacePtr(index).* = undefined;
5679 mod.namespaces_free_list.append(mod.gpa, index) catch {
5680 // In order to keep `destroyNamespace` a non-fallible function, we ignore memory
5681 // allocation failures here, instead leaking the Namespace until garbage collection.
5682 };
5683}
5684
5685pub fn createStruct(mod: *Module, initialization: Struct) Allocator.Error!Struct.Index {
5686 return mod.intern_pool.createStruct(mod.gpa, initialization);
5687}
5688
5689pub fn destroyStruct(mod: *Module, index: Struct.Index) void {
5690 return mod.intern_pool.destroyStruct(mod.gpa, index);
5691}
5692
5693pub fn createUnion(mod: *Module, initialization: Union) Allocator.Error!Union.Index {
5694 return mod.intern_pool.createUnion(mod.gpa, initialization);
5695}
5696
5697pub fn destroyUnion(mod: *Module, index: Union.Index) void {
5698 return mod.intern_pool.destroyUnion(mod.gpa, index);
5699}
5700
5701pub fn createFunc(mod: *Module, initialization: Fn) Allocator.Error!Fn.Index {
5702 return mod.intern_pool.createFunc(mod.gpa, initialization);
5703}
5704
5705pub fn destroyFunc(mod: *Module, index: Fn.Index) void {
5706 return mod.intern_pool.destroyFunc(mod.gpa, index);
5707}
5708
58725709pub fn allocateNewDecl(
58735710 mod: *Module,
5874 namespace: *Namespace,
5711 namespace: Namespace.Index,
58755712 src_node: Ast.Node.Index,
58765713 src_scope: ?*CaptureScope,
58775714) !Decl.Index {
......@@ -5896,6 +5733,7 @@ pub fn allocateNewDecl(
58965733 };
58975734 };
58985735
5736 if (src_scope) |scope| scope.incRef();
58995737 decl_and_index.new_decl.* = .{
59005738 .name = undefined,
59015739 .src_namespace = namespace,
......@@ -5906,7 +5744,7 @@ pub fn allocateNewDecl(
59065744 .ty = undefined,
59075745 .val = undefined,
59085746 .@"align" = undefined,
5909 .@"linksection" = undefined,
5747 .@"linksection" = .none,
59105748 .@"addrspace" = .generic,
59115749 .analysis = .unreferenced,
59125750 .deletion_flag = false,
......@@ -5924,25 +5762,20 @@ pub fn allocateNewDecl(
59245762 return decl_and_index.decl_index;
59255763}
59265764
5927/// Get error value for error tag `name`.
5928pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged(ErrorInt).KV {
5765pub fn getErrorValue(
5766 mod: *Module,
5767 name: InternPool.NullTerminatedString,
5768) Allocator.Error!ErrorInt {
59295769 const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
5930 if (gop.found_existing) {
5931 return std.StringHashMapUnmanaged(ErrorInt).KV{
5932 .key = gop.key_ptr.*,
5933 .value = gop.value_ptr.*,
5934 };
5935 }
5770 return @intCast(ErrorInt, gop.index);
5771}
59365772
5937 errdefer assert(mod.global_error_set.remove(name));
5938 try mod.error_name_list.ensureUnusedCapacity(mod.gpa, 1);
5939 gop.key_ptr.* = try mod.gpa.dupe(u8, name);
5940 gop.value_ptr.* = @intCast(ErrorInt, mod.error_name_list.items.len);
5941 mod.error_name_list.appendAssumeCapacity(gop.key_ptr.*);
5942 return std.StringHashMapUnmanaged(ErrorInt).KV{
5943 .key = gop.key_ptr.*,
5944 .value = gop.value_ptr.*,
5945 };
5773pub fn getErrorValueFromSlice(
5774 mod: *Module,
5775 name: []const u8,
5776) Allocator.Error!ErrorInt {
5777 const interned_name = try mod.intern_pool.getOrPutString(mod.gpa, name);
5778 return getErrorValue(mod, interned_name);
59465779}
59475780
59485781pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index {
......@@ -5953,29 +5786,28 @@ pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedV
59535786pub fn createAnonymousDeclFromDecl(
59545787 mod: *Module,
59555788 src_decl: *Decl,
5956 namespace: *Namespace,
5789 namespace: Namespace.Index,
59575790 src_scope: ?*CaptureScope,
59585791 tv: TypedValue,
59595792) !Decl.Index {
59605793 const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope);
59615794 errdefer mod.destroyDecl(new_decl_index);
5962 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
5963 src_decl.name, @enumToInt(new_decl_index),
5795 const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{
5796 src_decl.name.fmt(&mod.intern_pool), @enumToInt(new_decl_index),
59645797 });
59655798 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, tv, name);
59665799 return new_decl_index;
59675800}
59685801
5969/// Takes ownership of `name` even if it returns an error.
59705802pub fn initNewAnonDecl(
59715803 mod: *Module,
59725804 new_decl_index: Decl.Index,
59735805 src_line: u32,
5974 namespace: *Namespace,
5806 namespace: Namespace.Index,
59755807 typed_value: TypedValue,
5976 name: [:0]u8,
5977) !void {
5978 errdefer mod.gpa.free(name);
5808 name: InternPool.NullTerminatedString,
5809) Allocator.Error!void {
5810 assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern()));
59795811
59805812 const new_decl = mod.declPtr(new_decl_index);
59815813
......@@ -5984,34 +5816,12 @@ pub fn initNewAnonDecl(
59845816 new_decl.ty = typed_value.ty;
59855817 new_decl.val = typed_value.val;
59865818 new_decl.@"align" = 0;
5987 new_decl.@"linksection" = null;
5819 new_decl.@"linksection" = .none;
59885820 new_decl.has_tv = true;
59895821 new_decl.analysis = .complete;
59905822 new_decl.generation = mod.generation;
59915823
5992 try namespace.anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
5993
5994 // The Decl starts off with alive=false and the codegen backend will set alive=true
5995 // if the Decl is referenced by an instruction or another constant. Otherwise,
5996 // the Decl will be garbage collected by the `codegen_decl` task instead of sent
5997 // to the linker.
5998 if (typed_value.ty.isFnOrHasRuntimeBits()) {
5999 try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index });
6000 }
6001}
6002
6003pub fn makeIntType(arena: Allocator, signedness: std.builtin.Signedness, bits: u16) !Type {
6004 const int_payload = try arena.create(Type.Payload.Bits);
6005 int_payload.* = .{
6006 .base = .{
6007 .tag = switch (signedness) {
6008 .signed => .int_signed,
6009 .unsigned => .int_unsigned,
6010 },
6011 },
6012 .data = bits,
6013 };
6014 return Type.initPayload(&int_payload.base);
5824 try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {});
60155825}
60165826
60175827pub fn errNoteNonLazy(
......@@ -6073,16 +5883,17 @@ pub const SwitchProngSrc = union(enum) {
60735883 /// the LazySrcLoc in order to emit a compile error.
60745884 pub fn resolve(
60755885 prong_src: SwitchProngSrc,
6076 gpa: Allocator,
5886 mod: *Module,
60775887 decl: *Decl,
60785888 switch_node_offset: i32,
60795889 range_expand: RangeExpand,
60805890 ) LazySrcLoc {
60815891 @setCold(true);
6082 const tree = decl.getFileScope().getTree(gpa) catch |err| {
5892 const gpa = mod.gpa;
5893 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
60835894 // In this case we emit a warning + a less precise source location.
60845895 log.warn("unable to load {s}: {s}", .{
6085 decl.getFileScope().sub_file_path, @errorName(err),
5896 decl.getFileScope(mod).sub_file_path, @errorName(err),
60865897 });
60875898 return LazySrcLoc.nodeOffset(0);
60885899 };
......@@ -6166,11 +5977,12 @@ pub const PeerTypeCandidateSrc = union(enum) {
61665977
61675978 pub fn resolve(
61685979 self: PeerTypeCandidateSrc,
6169 gpa: Allocator,
5980 mod: *Module,
61705981 decl: *Decl,
61715982 candidate_i: usize,
61725983 ) ?LazySrcLoc {
61735984 @setCold(true);
5985 const gpa = mod.gpa;
61745986
61755987 switch (self) {
61765988 .none => {
......@@ -6192,10 +6004,10 @@ pub const PeerTypeCandidateSrc = union(enum) {
61926004 else => {},
61936005 }
61946006
6195 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6007 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
61966008 // In this case we emit a warning + a less precise source location.
61976009 log.warn("unable to load {s}: {s}", .{
6198 decl.getFileScope().sub_file_path, @errorName(err),
6010 decl.getFileScope(mod).sub_file_path, @errorName(err),
61996011 });
62006012 return LazySrcLoc.nodeOffset(0);
62016013 };
......@@ -6254,15 +6066,16 @@ fn queryFieldSrc(
62546066
62556067pub fn paramSrc(
62566068 func_node_offset: i32,
6257 gpa: Allocator,
6069 mod: *Module,
62586070 decl: *Decl,
62596071 param_i: usize,
62606072) LazySrcLoc {
62616073 @setCold(true);
6262 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6074 const gpa = mod.gpa;
6075 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
62636076 // In this case we emit a warning + a less precise source location.
62646077 log.warn("unable to load {s}: {s}", .{
6265 decl.getFileScope().sub_file_path, @errorName(err),
6078 decl.getFileScope(mod).sub_file_path, @errorName(err),
62666079 });
62676080 return LazySrcLoc.nodeOffset(0);
62686081 };
......@@ -6284,19 +6097,20 @@ pub fn paramSrc(
62846097}
62856098
62866099pub fn argSrc(
6100 mod: *Module,
62876101 call_node_offset: i32,
6288 gpa: Allocator,
62896102 decl: *Decl,
62906103 start_arg_i: usize,
62916104 bound_arg_src: ?LazySrcLoc,
62926105) LazySrcLoc {
6106 @setCold(true);
6107 const gpa = mod.gpa;
62936108 if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?;
62946109 const arg_i = start_arg_i - @boolToInt(bound_arg_src != null);
6295 @setCold(true);
6296 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6110 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
62976111 // In this case we emit a warning + a less precise source location.
62986112 log.warn("unable to load {s}: {s}", .{
6299 decl.getFileScope().sub_file_path, @errorName(err),
6113 decl.getFileScope(mod).sub_file_path, @errorName(err),
63006114 });
63016115 return LazySrcLoc.nodeOffset(0);
63026116 };
......@@ -6310,7 +6124,7 @@ pub fn argSrc(
63106124 const node_datas = tree.nodes.items(.data);
63116125 const call_args_node = tree.extra_data[node_datas[node].rhs - 1];
63126126 const call_args_offset = decl.nodeIndexToRelative(call_args_node);
6313 return initSrc(call_args_offset, gpa, decl, arg_i);
6127 return mod.initSrc(call_args_offset, decl, arg_i);
63146128 },
63156129 else => unreachable,
63166130 };
......@@ -6318,16 +6132,17 @@ pub fn argSrc(
63186132}
63196133
63206134pub fn initSrc(
6135 mod: *Module,
63216136 init_node_offset: i32,
6322 gpa: Allocator,
63236137 decl: *Decl,
63246138 init_index: usize,
63256139) LazySrcLoc {
63266140 @setCold(true);
6327 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6141 const gpa = mod.gpa;
6142 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
63286143 // In this case we emit a warning + a less precise source location.
63296144 log.warn("unable to load {s}: {s}", .{
6330 decl.getFileScope().sub_file_path, @errorName(err),
6145 decl.getFileScope(mod).sub_file_path, @errorName(err),
63316146 });
63326147 return LazySrcLoc.nodeOffset(0);
63336148 };
......@@ -6363,12 +6178,13 @@ pub fn initSrc(
63636178 }
63646179}
63656180
6366pub fn optionsSrc(gpa: Allocator, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
6181pub fn optionsSrc(mod: *Module, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
63676182 @setCold(true);
6368 const tree = decl.getFileScope().getTree(gpa) catch |err| {
6183 const gpa = mod.gpa;
6184 const tree = decl.getFileScope(mod).getTree(gpa) catch |err| {
63696185 // In this case we emit a warning + a less precise source location.
63706186 log.warn("unable to load {s}: {s}", .{
6371 decl.getFileScope().sub_file_path, @errorName(err),
6187 decl.getFileScope(mod).sub_file_path, @errorName(err),
63726188 });
63736189 return LazySrcLoc.nodeOffset(0);
63746190 };
......@@ -6430,11 +6246,13 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
64306246 // deletion set at this time.
64316247 for (file.deleted_decls.items) |decl_index| {
64326248 const decl = mod.declPtr(decl_index);
6433 log.debug("deleted from source: {*} ({s})", .{ decl, decl.name });
64346249
64356250 // Remove from the namespace it resides in, preserving declaration order.
64366251 assert(decl.zir_decl_index != 0);
6437 _ = decl.src_namespace.decls.orderedRemoveAdapted(@as([]const u8, mem.sliceTo(decl.name, 0)), DeclAdapter{ .mod = mod });
6252 _ = mod.namespacePtr(decl.src_namespace).decls.orderedRemoveAdapted(
6253 decl.name,
6254 DeclAdapter{ .mod = mod },
6255 );
64386256
64396257 try mod.clearDecl(decl_index, &outdated_decls);
64406258 mod.destroyDecl(decl_index);
......@@ -6454,7 +6272,7 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void {
64546272pub fn processExports(mod: *Module) !void {
64556273 const gpa = mod.gpa;
64566274 // Map symbol names to `Export` for name collision detection.
6457 var symbol_exports: std.StringArrayHashMapUnmanaged(*Export) = .{};
6275 var symbol_exports: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, *Export) = .{};
64586276 defer symbol_exports.deinit(gpa);
64596277
64606278 var it = mod.decl_exports.iterator();
......@@ -6462,13 +6280,13 @@ pub fn processExports(mod: *Module) !void {
64626280 const exported_decl = entry.key_ptr.*;
64636281 const exports = entry.value_ptr.items;
64646282 for (exports) |new_export| {
6465 const gop = try symbol_exports.getOrPut(gpa, new_export.options.name);
6283 const gop = try symbol_exports.getOrPut(gpa, new_export.opts.name);
64666284 if (gop.found_existing) {
64676285 new_export.status = .failed_retryable;
64686286 try mod.failed_exports.ensureUnusedCapacity(gpa, 1);
64696287 const src_loc = new_export.getSrcLoc(mod);
6470 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {s}", .{
6471 new_export.options.name,
6288 const msg = try ErrorMsg.create(gpa, src_loc, "exported symbol collision: {}", .{
6289 new_export.opts.name.fmt(&mod.intern_pool),
64726290 });
64736291 errdefer msg.destroy(gpa);
64746292 const other_export = gop.value_ptr.*;
......@@ -6501,11 +6319,16 @@ pub fn populateTestFunctions(
65016319 main_progress_node: *std.Progress.Node,
65026320) !void {
65036321 const gpa = mod.gpa;
6322 const ip = &mod.intern_pool;
65046323 const builtin_pkg = mod.main_pkg.table.get("builtin").?;
65056324 const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file;
65066325 const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?);
6507 const builtin_namespace = root_decl.src_namespace;
6508 const decl_index = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{ .mod = mod }).?;
6326 const builtin_namespace = mod.namespacePtr(root_decl.src_namespace);
6327 const test_functions_str = try ip.getOrPutString(gpa, "test_functions");
6328 const decl_index = builtin_namespace.decls.getKeyAdapted(
6329 test_functions_str,
6330 DeclAdapter{ .mod = mod },
6331 ).?;
65096332 {
65106333 // We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions`
65116334 // was not referenced by start code.
......@@ -6518,90 +6341,117 @@ pub fn populateTestFunctions(
65186341 try mod.ensureDeclAnalyzed(decl_index);
65196342 }
65206343 const decl = mod.declPtr(decl_index);
6521 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
6522 const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType();
6344 const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod);
6345 const null_usize = try mod.intern(.{ .opt = .{
6346 .ty = try mod.intern(.{ .opt_type = .usize_type }),
6347 .val = .none,
6348 } });
65236349
65246350 const array_decl_index = d: {
65256351 // Add mod.test_functions to an array decl then make the test_functions
65266352 // decl reference it as a slice.
6527 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
6528 errdefer new_decl_arena.deinit();
6529 const arena = new_decl_arena.allocator();
6530
6531 const test_fn_vals = try arena.alloc(Value, mod.test_functions.count());
6532 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
6533 .ty = try Type.Tag.array.create(arena, .{
6534 .len = test_fn_vals.len,
6535 .elem_type = try tmp_test_fn_ty.copy(arena),
6536 }),
6537 .val = try Value.Tag.aggregate.create(arena, test_fn_vals),
6538 });
6539 const array_decl = mod.declPtr(array_decl_index);
6353 const test_fn_vals = try gpa.alloc(InternPool.Index, mod.test_functions.count());
6354 defer gpa.free(test_fn_vals);
65406355
65416356 // Add a dependency on each test name and function pointer.
6542 try array_decl.dependencies.ensureUnusedCapacity(gpa, test_fn_vals.len * 2);
6357 var array_decl_dependencies = std.ArrayListUnmanaged(Decl.Index){};
6358 defer array_decl_dependencies.deinit(gpa);
6359 try array_decl_dependencies.ensureUnusedCapacity(gpa, test_fn_vals.len * 2);
65436360
6544 for (mod.test_functions.keys(), 0..) |test_decl_index, i| {
6361 for (test_fn_vals, mod.test_functions.keys()) |*test_fn_val, test_decl_index| {
65456362 const test_decl = mod.declPtr(test_decl_index);
6546 const test_name_slice = mem.sliceTo(test_decl.name, 0);
6363 // TODO: write something like getCoercedInts to avoid needing to dupe
6364 const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(test_decl.name));
6365 defer gpa.free(test_decl_name);
65476366 const test_name_decl_index = n: {
6548 var name_decl_arena = std.heap.ArenaAllocator.init(gpa);
6549 errdefer name_decl_arena.deinit();
6550 const bytes = try name_decl_arena.allocator().dupe(u8, test_name_slice);
6551 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{
6552 .ty = try Type.Tag.array_u8.create(name_decl_arena.allocator(), bytes.len),
6553 .val = try Value.Tag.bytes.create(name_decl_arena.allocator(), bytes),
6367 const test_name_decl_ty = try mod.arrayType(.{
6368 .len = test_decl_name.len,
6369 .child = .u8_type,
6370 });
6371 const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
6372 .ty = test_name_decl_ty,
6373 .val = (try mod.intern(.{ .aggregate = .{
6374 .ty = test_name_decl_ty.toIntern(),
6375 .storage = .{ .bytes = test_decl_name },
6376 } })).toValue(),
65546377 });
6555 try mod.declPtr(test_name_decl_index).finalizeNewArena(&name_decl_arena);
65566378 break :n test_name_decl_index;
65576379 };
6558 array_decl.dependencies.putAssumeCapacityNoClobber(test_decl_index, .normal);
6559 array_decl.dependencies.putAssumeCapacityNoClobber(test_name_decl_index, .normal);
6380 array_decl_dependencies.appendAssumeCapacity(test_decl_index);
6381 array_decl_dependencies.appendAssumeCapacity(test_name_decl_index);
65606382 try mod.linkerUpdateDecl(test_name_decl_index);
65616383
6562 const field_vals = try arena.create([3]Value);
6563 field_vals.* = .{
6564 try Value.Tag.slice.create(arena, .{
6565 .ptr = try Value.Tag.decl_ref.create(arena, test_name_decl_index),
6566 .len = try Value.Tag.int_u64.create(arena, test_name_slice.len),
6567 }), // name
6568 try Value.Tag.decl_ref.create(arena, test_decl_index), // func
6569 Value.initTag(.null_value), // async_frame_size
6384 const test_fn_fields = .{
6385 // name
6386 try mod.intern(.{ .ptr = .{
6387 .ty = .slice_const_u8_type,
6388 .addr = .{ .decl = test_name_decl_index },
6389 .len = try mod.intern(.{ .int = .{
6390 .ty = .usize_type,
6391 .storage = .{ .u64 = test_decl_name.len },
6392 } }),
6393 } }),
6394 // func
6395 try mod.intern(.{ .ptr = .{
6396 .ty = try mod.intern(.{ .ptr_type = .{
6397 .child = test_decl.ty.toIntern(),
6398 .flags = .{
6399 .is_const = true,
6400 },
6401 } }),
6402 .addr = .{ .decl = test_decl_index },
6403 } }),
6404 // async_frame_size
6405 null_usize,
65706406 };
6571 test_fn_vals[i] = try Value.Tag.aggregate.create(arena, field_vals);
6407 test_fn_val.* = try mod.intern(.{ .aggregate = .{
6408 .ty = test_fn_ty.toIntern(),
6409 .storage = .{ .elems = &test_fn_fields },
6410 } });
6411 }
6412
6413 const array_decl_ty = try mod.arrayType(.{
6414 .len = test_fn_vals.len,
6415 .child = test_fn_ty.toIntern(),
6416 .sentinel = .none,
6417 });
6418 const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{
6419 .ty = array_decl_ty,
6420 .val = (try mod.intern(.{ .aggregate = .{
6421 .ty = array_decl_ty.toIntern(),
6422 .storage = .{ .elems = test_fn_vals },
6423 } })).toValue(),
6424 });
6425 for (array_decl_dependencies.items) |array_decl_dependency| {
6426 try mod.declareDeclDependency(array_decl_index, array_decl_dependency);
65726427 }
65736428
6574 try array_decl.finalizeNewArena(&new_decl_arena);
65756429 break :d array_decl_index;
65766430 };
65776431 try mod.linkerUpdateDecl(array_decl_index);
65786432
65796433 {
6580 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
6581 errdefer new_decl_arena.deinit();
6582 const arena = new_decl_arena.allocator();
6583
6584 {
6585 // This copy accesses the old Decl Type/Value so it must be done before `clearValues`.
6586 const new_ty = try Type.Tag.const_slice.create(arena, try tmp_test_fn_ty.copy(arena));
6587 const new_var = try gpa.create(Var);
6588 errdefer gpa.destroy(new_var);
6589 new_var.* = decl.val.castTag(.variable).?.data.*;
6590 new_var.init = try Value.Tag.slice.create(arena, .{
6591 .ptr = try Value.Tag.decl_ref.create(arena, array_decl_index),
6592 .len = try Value.Tag.int_u64.create(arena, mod.test_functions.count()),
6593 });
6594 const new_val = try Value.Tag.variable.create(arena, new_var);
6595
6596 // Since we are replacing the Decl's value we must perform cleanup on the
6597 // previous value.
6598 decl.clearValues(mod);
6599 decl.ty = new_ty;
6600 decl.val = new_val;
6601 decl.has_tv = true;
6602 }
6603
6604 try decl.finalizeNewArena(&new_decl_arena);
6434 const new_ty = try mod.ptrType(.{
6435 .child = test_fn_ty.toIntern(),
6436 .flags = .{
6437 .is_const = true,
6438 .size = .Slice,
6439 },
6440 });
6441 const new_val = decl.val;
6442 const new_init = try mod.intern(.{ .ptr = .{
6443 .ty = new_ty.toIntern(),
6444 .addr = .{ .decl = array_decl_index },
6445 .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(),
6446 } });
6447 ip.mutateVarInit(decl.val.toIntern(), new_init);
6448
6449 // Since we are replacing the Decl's value we must perform cleanup on the
6450 // previous value.
6451 decl.clearValues(mod);
6452 decl.ty = new_ty;
6453 decl.val = new_val;
6454 decl.has_tv = true;
66056455 }
66066456 try mod.linkerUpdateDecl(decl_index);
66076457}
......@@ -6631,7 +6481,7 @@ pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void {
66316481 try mod.failed_decls.ensureUnusedCapacity(gpa, 1);
66326482 mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create(
66336483 gpa,
6634 decl.srcLoc(),
6484 decl.srcLoc(mod),
66356485 "unable to codegen: {s}",
66366486 .{@errorName(err)},
66376487 ));
......@@ -6673,64 +6523,49 @@ fn reportRetryableFileError(
66736523 gop.value_ptr.* = err_msg;
66746524}
66756525
6676pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {
6677 switch (val.tag()) {
6678 .decl_ref_mut => return mod.markDeclIndexAlive(val.castTag(.decl_ref_mut).?.data.decl_index),
6679 .extern_fn => return mod.markDeclIndexAlive(val.castTag(.extern_fn).?.data.owner_decl),
6680 .function => return mod.markDeclIndexAlive(val.castTag(.function).?.data.owner_decl),
6681 .variable => return mod.markDeclIndexAlive(val.castTag(.variable).?.data.owner_decl),
6682 .decl_ref => return mod.markDeclIndexAlive(val.cast(Value.Payload.Decl).?.data),
6683
6684 .repeated,
6685 .eu_payload,
6686 .opt_payload,
6687 .empty_array_sentinel,
6688 => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.SubValue).?.data),
6689
6690 .eu_payload_ptr,
6691 .opt_payload_ptr,
6692 => return mod.markReferencedDeclsAlive(val.cast(Value.Payload.PayloadPtr).?.data.container_ptr),
6693
6694 .slice => {
6695 const slice = val.cast(Value.Payload.Slice).?.data;
6696 mod.markReferencedDeclsAlive(slice.ptr);
6697 mod.markReferencedDeclsAlive(slice.len);
6698 },
6699
6700 .elem_ptr => {
6701 const elem_ptr = val.cast(Value.Payload.ElemPtr).?.data;
6702 return mod.markReferencedDeclsAlive(elem_ptr.array_ptr);
6703 },
6704 .field_ptr => {
6705 const field_ptr = val.cast(Value.Payload.FieldPtr).?.data;
6706 return mod.markReferencedDeclsAlive(field_ptr.container_ptr);
6526pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
6527 switch (mod.intern_pool.indexToKey(val.toIntern())) {
6528 .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
6529 .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
6530 .func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
6531 .error_union => |error_union| switch (error_union.val) {
6532 .err_name => {},
6533 .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
67076534 },
6708 .aggregate => {
6709 for (val.castTag(.aggregate).?.data) |field_val| {
6710 mod.markReferencedDeclsAlive(field_val);
6535 .ptr => |ptr| {
6536 switch (ptr.addr) {
6537 .decl => |decl| try mod.markDeclIndexAlive(decl),
6538 .mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl),
6539 .int, .comptime_field => {},
6540 .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(parent.toValue()),
6541 .elem, .field => |base_index| try mod.markReferencedDeclsAlive(base_index.base.toValue()),
67116542 }
6543 if (ptr.len != .none) try mod.markReferencedDeclsAlive(ptr.len.toValue());
67126544 },
6713 .@"union" => {
6714 const data = val.cast(Value.Payload.Union).?.data;
6715 mod.markReferencedDeclsAlive(data.tag);
6716 mod.markReferencedDeclsAlive(data.val);
6545 .opt => |opt| if (opt.val != .none) try mod.markReferencedDeclsAlive(opt.val.toValue()),
6546 .aggregate => |aggregate| for (aggregate.storage.values()) |elem|
6547 try mod.markReferencedDeclsAlive(elem.toValue()),
6548 .un => |un| {
6549 try mod.markReferencedDeclsAlive(un.tag.toValue());
6550 try mod.markReferencedDeclsAlive(un.val.toValue());
67176551 },
6718
67196552 else => {},
67206553 }
67216554}
67226555
6723pub fn markDeclAlive(mod: *Module, decl: *Decl) void {
6556pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {
67246557 if (decl.alive) return;
67256558 decl.alive = true;
67266559
6560 try decl.intern(mod);
6561
67276562 // This is the first time we are marking this Decl alive. We must
67286563 // therefore recurse into its value and mark any Decl it references
67296564 // as also alive, so that any Decl referenced does not get garbage collected.
6730 mod.markReferencedDeclsAlive(decl.val);
6565 try mod.markReferencedDeclsAlive(decl.val);
67316566}
67326567
6733fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) void {
6568fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
67346569 return mod.markDeclAlive(mod.declPtr(decl_index));
67356570}
67366571
......@@ -6779,3 +6614,522 @@ pub fn backendSupportsFeature(mod: Module, feature: Feature) bool {
67796614 .field_reordering => mod.comp.bin_file.options.use_llvm,
67806615 };
67816616}
6617
6618/// Shortcut for calling `intern_pool.get`.
6619pub fn intern(mod: *Module, key: InternPool.Key) Allocator.Error!InternPool.Index {
6620 return mod.intern_pool.get(mod.gpa, key);
6621}
6622
6623/// Shortcut for calling `intern_pool.getCoerced`.
6624pub fn getCoerced(mod: *Module, val: Value, new_ty: Type) Allocator.Error!Value {
6625 return (try mod.intern_pool.getCoerced(mod.gpa, val.toIntern(), new_ty.toIntern())).toValue();
6626}
6627
6628pub fn intType(mod: *Module, signedness: std.builtin.Signedness, bits: u16) Allocator.Error!Type {
6629 return (try intern(mod, .{ .int_type = .{
6630 .signedness = signedness,
6631 .bits = bits,
6632 } })).toType();
6633}
6634
6635pub fn arrayType(mod: *Module, info: InternPool.Key.ArrayType) Allocator.Error!Type {
6636 const i = try intern(mod, .{ .array_type = info });
6637 return i.toType();
6638}
6639
6640pub fn vectorType(mod: *Module, info: InternPool.Key.VectorType) Allocator.Error!Type {
6641 const i = try intern(mod, .{ .vector_type = info });
6642 return i.toType();
6643}
6644
6645pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!Type {
6646 const i = try intern(mod, .{ .opt_type = child_type });
6647 return i.toType();
6648}
6649
6650pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
6651 var canon_info = info;
6652 const have_elem_layout = info.child.toType().layoutIsResolved(mod);
6653
6654 if (info.flags.size == .C) canon_info.flags.is_allowzero = true;
6655
6656 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
6657 // type, we change it to 0 here. If this causes an assertion trip because the
6658 // pointee type needs to be resolved more, that needs to be done before calling
6659 // this ptr() function.
6660 if (info.flags.alignment.toByteUnitsOptional()) |info_align| {
6661 if (have_elem_layout and info_align == info.child.toType().abiAlignment(mod)) {
6662 canon_info.flags.alignment = .none;
6663 }
6664 }
6665
6666 switch (info.flags.vector_index) {
6667 // Canonicalize host_size. If it matches the bit size of the pointee type,
6668 // we change it to 0 here. If this causes an assertion trip, the pointee type
6669 // needs to be resolved before calling this ptr() function.
6670 .none => if (have_elem_layout and info.packed_offset.host_size != 0) {
6671 const elem_bit_size = info.child.toType().bitSize(mod);
6672 assert(info.packed_offset.bit_offset + elem_bit_size <= info.packed_offset.host_size * 8);
6673 if (info.packed_offset.host_size * 8 == elem_bit_size) {
6674 canon_info.packed_offset.host_size = 0;
6675 }
6676 },
6677 .runtime => {},
6678 _ => assert(@enumToInt(info.flags.vector_index) < info.packed_offset.host_size),
6679 }
6680
6681 return (try intern(mod, .{ .ptr_type = canon_info })).toType();
6682}
6683
6684pub fn singleMutPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6685 return ptrType(mod, .{ .child = child_type.toIntern() });
6686}
6687
6688pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6689 return ptrType(mod, .{
6690 .child = child_type.toIntern(),
6691 .flags = .{
6692 .is_const = true,
6693 },
6694 });
6695}
6696
6697pub fn manyConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
6698 return ptrType(mod, .{
6699 .child = child_type.toIntern(),
6700 .flags = .{
6701 .size = .Many,
6702 .is_const = true,
6703 },
6704 });
6705}
6706
6707pub fn adjustPtrTypeChild(mod: *Module, ptr_ty: Type, new_child: Type) Allocator.Error!Type {
6708 const info = Type.ptrInfoIp(&mod.intern_pool, ptr_ty.toIntern());
6709 return mod.ptrType(.{
6710 .child = new_child.toIntern(),
6711 .sentinel = info.sentinel,
6712 .flags = info.flags,
6713 .packed_offset = info.packed_offset,
6714 });
6715}
6716
6717pub fn funcType(mod: *Module, info: InternPool.Key.FuncType) Allocator.Error!Type {
6718 return (try intern(mod, .{ .func_type = info })).toType();
6719}
6720
6721/// Use this for `anyframe->T` only.
6722/// For `anyframe`, use the `InternPool.Index.anyframe` tag directly.
6723pub fn anyframeType(mod: *Module, payload_ty: Type) Allocator.Error!Type {
6724 return (try intern(mod, .{ .anyframe_type = payload_ty.toIntern() })).toType();
6725}
6726
6727pub fn errorUnionType(mod: *Module, error_set_ty: Type, payload_ty: Type) Allocator.Error!Type {
6728 return (try intern(mod, .{ .error_union_type = .{
6729 .error_set_type = error_set_ty.toIntern(),
6730 .payload_type = payload_ty.toIntern(),
6731 } })).toType();
6732}
6733
6734pub fn singleErrorSetType(mod: *Module, name: InternPool.NullTerminatedString) Allocator.Error!Type {
6735 const names: *const [1]InternPool.NullTerminatedString = &name;
6736 return (try mod.intern_pool.get(mod.gpa, .{ .error_set_type = .{ .names = names } })).toType();
6737}
6738
6739/// Sorts `names` in place.
6740pub fn errorSetFromUnsortedNames(
6741 mod: *Module,
6742 names: []InternPool.NullTerminatedString,
6743) Allocator.Error!Type {
6744 std.mem.sort(
6745 InternPool.NullTerminatedString,
6746 names,
6747 {},
6748 InternPool.NullTerminatedString.indexLessThan,
6749 );
6750 const new_ty = try mod.intern(.{ .error_set_type = .{ .names = names } });
6751 return new_ty.toType();
6752}
6753
6754/// Supports optionals in addition to pointers.
6755pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6756 return mod.getCoerced(try mod.intValue_u64(Type.usize, x), ty);
6757}
6758
6759/// Supports only pointers. See `ptrIntValue` for pointer-like optional support.
6760pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6761 assert(ty.zigTypeTag(mod) == .Pointer);
6762 const i = try intern(mod, .{ .ptr = .{
6763 .ty = ty.toIntern(),
6764 .addr = .{ .int = try mod.intValue_u64(Type.usize, x) },
6765 } });
6766 return i.toValue();
6767}
6768
6769/// Creates an enum tag value based on the integer tag value.
6770pub fn enumValue(mod: *Module, ty: Type, tag_int: InternPool.Index) Allocator.Error!Value {
6771 if (std.debug.runtime_safety) {
6772 const tag = ty.zigTypeTag(mod);
6773 assert(tag == .Enum);
6774 }
6775 const i = try intern(mod, .{ .enum_tag = .{
6776 .ty = ty.toIntern(),
6777 .int = tag_int,
6778 } });
6779 return i.toValue();
6780}
6781
6782/// Creates an enum tag value based on the field index according to source code
6783/// declaration order.
6784pub fn enumValueFieldIndex(mod: *Module, ty: Type, field_index: u32) Allocator.Error!Value {
6785 const ip = &mod.intern_pool;
6786 const gpa = mod.gpa;
6787 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
6788
6789 if (enum_type.values.len == 0) {
6790 // Auto-numbered fields.
6791 return (try ip.get(gpa, .{ .enum_tag = .{
6792 .ty = ty.toIntern(),
6793 .int = try ip.get(gpa, .{ .int = .{
6794 .ty = enum_type.tag_ty,
6795 .storage = .{ .u64 = field_index },
6796 } }),
6797 } })).toValue();
6798 }
6799
6800 return (try ip.get(gpa, .{ .enum_tag = .{
6801 .ty = ty.toIntern(),
6802 .int = enum_type.values[field_index],
6803 } })).toValue();
6804}
6805
6806pub fn intValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
6807 if (std.math.cast(u64, x)) |casted| return intValue_u64(mod, ty, casted);
6808 if (std.math.cast(i64, x)) |casted| return intValue_i64(mod, ty, casted);
6809 var limbs_buffer: [4]usize = undefined;
6810 var big_int = BigIntMutable.init(&limbs_buffer, x);
6811 return intValue_big(mod, ty, big_int.toConst());
6812}
6813
6814pub fn intValue_big(mod: *Module, ty: Type, x: BigIntConst) Allocator.Error!Value {
6815 const i = try intern(mod, .{ .int = .{
6816 .ty = ty.toIntern(),
6817 .storage = .{ .big_int = x },
6818 } });
6819 return i.toValue();
6820}
6821
6822pub fn intValue_u64(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
6823 const i = try intern(mod, .{ .int = .{
6824 .ty = ty.toIntern(),
6825 .storage = .{ .u64 = x },
6826 } });
6827 return i.toValue();
6828}
6829
6830pub fn intValue_i64(mod: *Module, ty: Type, x: i64) Allocator.Error!Value {
6831 const i = try intern(mod, .{ .int = .{
6832 .ty = ty.toIntern(),
6833 .storage = .{ .i64 = x },
6834 } });
6835 return i.toValue();
6836}
6837
6838pub fn unionValue(mod: *Module, union_ty: Type, tag: Value, val: Value) Allocator.Error!Value {
6839 const i = try intern(mod, .{ .un = .{
6840 .ty = union_ty.toIntern(),
6841 .tag = tag.toIntern(),
6842 .val = val.toIntern(),
6843 } });
6844 return i.toValue();
6845}
6846
6847/// This function casts the float representation down to the representation of the type, potentially
6848/// losing data if the representation wasn't correct.
6849pub fn floatValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
6850 const storage: InternPool.Key.Float.Storage = switch (ty.floatBits(mod.getTarget())) {
6851 16 => .{ .f16 = @floatCast(f16, x) },
6852 32 => .{ .f32 = @floatCast(f32, x) },
6853 64 => .{ .f64 = @floatCast(f64, x) },
6854 80 => .{ .f80 = @floatCast(f80, x) },
6855 128 => .{ .f128 = @floatCast(f128, x) },
6856 else => unreachable,
6857 };
6858 const i = try intern(mod, .{ .float = .{
6859 .ty = ty.toIntern(),
6860 .storage = storage,
6861 } });
6862 return i.toValue();
6863}
6864
6865pub fn nullValue(mod: *Module, opt_ty: Type) Allocator.Error!Value {
6866 const ip = &mod.intern_pool;
6867 assert(ip.isOptionalType(opt_ty.toIntern()));
6868 const result = try ip.get(mod.gpa, .{ .opt = .{
6869 .ty = opt_ty.toIntern(),
6870 .val = .none,
6871 } });
6872 return result.toValue();
6873}
6874
6875pub fn smallestUnsignedInt(mod: *Module, max: u64) Allocator.Error!Type {
6876 return intType(mod, .unsigned, Type.smallestUnsignedBits(max));
6877}
6878
6879/// Returns the smallest possible integer type containing both `min` and
6880/// `max`. Asserts that neither value is undef.
6881/// TODO: if #3806 is implemented, this becomes trivial
6882pub fn intFittingRange(mod: *Module, min: Value, max: Value) !Type {
6883 assert(!min.isUndef(mod));
6884 assert(!max.isUndef(mod));
6885
6886 if (std.debug.runtime_safety) {
6887 assert(Value.order(min, max, mod).compare(.lte));
6888 }
6889
6890 const sign = min.orderAgainstZero(mod) == .lt;
6891
6892 const min_val_bits = intBitsForValue(mod, min, sign);
6893 const max_val_bits = intBitsForValue(mod, max, sign);
6894
6895 return mod.intType(
6896 if (sign) .signed else .unsigned,
6897 @max(min_val_bits, max_val_bits),
6898 );
6899}
6900
6901/// Given a value representing an integer, returns the number of bits necessary to represent
6902/// this value in an integer. If `sign` is true, returns the number of bits necessary in a
6903/// twos-complement integer; otherwise in an unsigned integer.
6904/// Asserts that `val` is not undef. If `val` is negative, asserts that `sign` is true.
6905pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
6906 assert(!val.isUndef(mod));
6907
6908 const key = mod.intern_pool.indexToKey(val.toIntern());
6909 switch (key.int.storage) {
6910 .i64 => |x| {
6911 if (std.math.cast(u64, x)) |casted| return Type.smallestUnsignedBits(casted) + @boolToInt(sign);
6912 assert(sign);
6913 // Protect against overflow in the following negation.
6914 if (x == std.math.minInt(i64)) return 64;
6915 return Type.smallestUnsignedBits(@intCast(u64, -x - 1)) + 1;
6916 },
6917 .u64 => |x| {
6918 return Type.smallestUnsignedBits(x) + @boolToInt(sign);
6919 },
6920 .big_int => |big| {
6921 if (big.positive) return @intCast(u16, big.bitCountAbs() + @boolToInt(sign));
6922
6923 // Zero is still a possibility, in which case unsigned is fine
6924 if (big.eqZero()) return 0;
6925
6926 return @intCast(u16, big.bitCountTwosComp());
6927 },
6928 .lazy_align => |lazy_ty| {
6929 return Type.smallestUnsignedBits(lazy_ty.toType().abiAlignment(mod)) + @boolToInt(sign);
6930 },
6931 .lazy_size => |lazy_ty| {
6932 return Type.smallestUnsignedBits(lazy_ty.toType().abiSize(mod)) + @boolToInt(sign);
6933 },
6934 }
6935}
6936
6937pub const AtomicPtrAlignmentError = error{
6938 FloatTooBig,
6939 IntTooBig,
6940 BadType,
6941 OutOfMemory,
6942};
6943
6944pub const AtomicPtrAlignmentDiagnostics = struct {
6945 bits: u16 = undefined,
6946 max_bits: u16 = undefined,
6947};
6948
6949/// If ABI alignment of `ty` is OK for atomic operations, returns 0.
6950/// Otherwise returns the alignment required on a pointer for the target
6951/// to perform atomic operations.
6952// TODO this function does not take into account CPU features, which can affect
6953// this value. Audit this!
6954pub fn atomicPtrAlignment(
6955 mod: *Module,
6956 ty: Type,
6957 diags: *AtomicPtrAlignmentDiagnostics,
6958) AtomicPtrAlignmentError!u32 {
6959 const target = mod.getTarget();
6960 const max_atomic_bits: u16 = switch (target.cpu.arch) {
6961 .avr,
6962 .msp430,
6963 .spu_2,
6964 => 16,
6965
6966 .arc,
6967 .arm,
6968 .armeb,
6969 .hexagon,
6970 .m68k,
6971 .le32,
6972 .mips,
6973 .mipsel,
6974 .nvptx,
6975 .powerpc,
6976 .powerpcle,
6977 .r600,
6978 .riscv32,
6979 .sparc,
6980 .sparcel,
6981 .tce,
6982 .tcele,
6983 .thumb,
6984 .thumbeb,
6985 .x86,
6986 .xcore,
6987 .amdil,
6988 .hsail,
6989 .spir,
6990 .kalimba,
6991 .lanai,
6992 .shave,
6993 .wasm32,
6994 .renderscript32,
6995 .csky,
6996 .spirv32,
6997 .dxil,
6998 .loongarch32,
6999 .xtensa,
7000 => 32,
7001
7002 .amdgcn,
7003 .bpfel,
7004 .bpfeb,
7005 .le64,
7006 .mips64,
7007 .mips64el,
7008 .nvptx64,
7009 .powerpc64,
7010 .powerpc64le,
7011 .riscv64,
7012 .sparc64,
7013 .s390x,
7014 .amdil64,
7015 .hsail64,
7016 .spir64,
7017 .wasm64,
7018 .renderscript64,
7019 .ve,
7020 .spirv64,
7021 .loongarch64,
7022 => 64,
7023
7024 .aarch64,
7025 .aarch64_be,
7026 .aarch64_32,
7027 => 128,
7028
7029 .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .cx16)) 128 else 64,
7030 };
7031
7032 const int_ty = switch (ty.zigTypeTag(mod)) {
7033 .Int => ty,
7034 .Enum => ty.intTagType(mod),
7035 .Float => {
7036 const bit_count = ty.floatBits(target);
7037 if (bit_count > max_atomic_bits) {
7038 diags.* = .{
7039 .bits = bit_count,
7040 .max_bits = max_atomic_bits,
7041 };
7042 return error.FloatTooBig;
7043 }
7044 return 0;
7045 },
7046 .Bool => return 0,
7047 else => {
7048 if (ty.isPtrAtRuntime(mod)) return 0;
7049 return error.BadType;
7050 },
7051 };
7052
7053 const bit_count = int_ty.intInfo(mod).bits;
7054 if (bit_count > max_atomic_bits) {
7055 diags.* = .{
7056 .bits = bit_count,
7057 .max_bits = max_atomic_bits,
7058 };
7059 return error.IntTooBig;
7060 }
7061
7062 return 0;
7063}
7064
7065pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc {
7066 return mod.declPtr(opaque_type.decl).srcLoc(mod);
7067}
7068
7069pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) !InternPool.NullTerminatedString {
7070 return mod.declPtr(opaque_type.decl).getFullyQualifiedName(mod);
7071}
7072
7073pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File {
7074 return mod.declPtr(decl_index).getFileScope(mod);
7075}
7076
7077pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index {
7078 return mod.namespacePtr(namespace_index).getDeclIndex(mod);
7079}
7080
7081/// Returns null in the following cases:
7082/// * `@TypeOf(.{})`
7083/// * A struct which has no fields (`struct {}`).
7084/// * Not a struct.
7085pub fn typeToStruct(mod: *Module, ty: Type) ?*Struct {
7086 if (ty.ip_index == .none) return null;
7087 const struct_index = mod.intern_pool.indexToStructType(ty.toIntern()).unwrap() orelse return null;
7088 return mod.structPtr(struct_index);
7089}
7090
7091pub fn typeToUnion(mod: *Module, ty: Type) ?*Union {
7092 if (ty.ip_index == .none) return null;
7093 const union_index = mod.intern_pool.indexToUnionType(ty.toIntern()).unwrap() orelse return null;
7094 return mod.unionPtr(union_index);
7095}
7096
7097pub fn typeToFunc(mod: *Module, ty: Type) ?InternPool.Key.FuncType {
7098 if (ty.ip_index == .none) return null;
7099 return mod.intern_pool.indexToFuncType(ty.toIntern());
7100}
7101
7102pub fn typeToInferredErrorSet(mod: *Module, ty: Type) ?*Fn.InferredErrorSet {
7103 const index = typeToInferredErrorSetIndex(mod, ty).unwrap() orelse return null;
7104 return mod.inferredErrorSetPtr(index);
7105}
7106
7107pub fn typeToInferredErrorSetIndex(mod: *Module, ty: Type) Fn.InferredErrorSet.OptionalIndex {
7108 if (ty.ip_index == .none) return .none;
7109 return mod.intern_pool.indexToInferredErrorSetType(ty.toIntern());
7110}
7111
7112pub fn fieldSrcLoc(mod: *Module, owner_decl_index: Decl.Index, query: FieldSrcQuery) SrcLoc {
7113 @setCold(true);
7114 const owner_decl = mod.declPtr(owner_decl_index);
7115 const file = owner_decl.getFileScope(mod);
7116 const tree = file.getTree(mod.gpa) catch |err| {
7117 // In this case we emit a warning + a less precise source location.
7118 log.warn("unable to load {s}: {s}", .{
7119 file.sub_file_path, @errorName(err),
7120 });
7121 return owner_decl.srcLoc(mod);
7122 };
7123 const node = owner_decl.relativeToNodeIndex(0);
7124 var buf: [2]Ast.Node.Index = undefined;
7125 if (tree.fullContainerDecl(&buf, node)) |container_decl| {
7126 return queryFieldSrc(tree.*, query, file, container_decl);
7127 } else {
7128 // This type was generated using @Type
7129 return owner_decl.srcLoc(mod);
7130 }
7131}
7132
7133pub fn toEnum(mod: *Module, comptime E: type, val: Value) E {
7134 return mod.intern_pool.toEnum(E, val.toIntern());
7135}
src/RangeSet.zig+33-26
......@@ -1,18 +1,18 @@
11const std = @import("std");
2const assert = std.debug.assert;
23const Order = std.math.Order;
34
4const RangeSet = @This();
5const InternPool = @import("InternPool.zig");
56const Module = @import("Module.zig");
7const RangeSet = @This();
68const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
7const Type = @import("type.zig").Type;
8const Value = @import("value.zig").Value;
99
1010ranges: std.ArrayList(Range),
1111module: *Module,
1212
1313pub const Range = struct {
14 first: Value,
15 last: Value,
14 first: InternPool.Index,
15 last: InternPool.Index,
1616 src: SwitchProngSrc,
1717};
1818
......@@ -29,18 +29,27 @@ pub fn deinit(self: *RangeSet) void {
2929
3030pub fn add(
3131 self: *RangeSet,
32 first: Value,
33 last: Value,
34 ty: Type,
32 first: InternPool.Index,
33 last: InternPool.Index,
3534 src: SwitchProngSrc,
3635) !?SwitchProngSrc {
36 const mod = self.module;
37 const ip = &mod.intern_pool;
38
39 const ty = ip.typeOf(first);
40 assert(ty == ip.typeOf(last));
41
3742 for (self.ranges.items) |range| {
38 if (last.compareAll(.gte, range.first, ty, self.module) and
39 first.compareAll(.lte, range.last, ty, self.module))
43 assert(ty == ip.typeOf(range.first));
44 assert(ty == ip.typeOf(range.last));
45
46 if (last.toValue().compareScalar(.gte, range.first.toValue(), ty.toType(), mod) and
47 first.toValue().compareScalar(.lte, range.last.toValue(), ty.toType(), mod))
4048 {
4149 return range.src; // They overlap.
4250 }
4351 }
52
4453 try self.ranges.append(.{
4554 .first = first,
4655 .last = last,
......@@ -49,45 +58,43 @@ pub fn add(
4958 return null;
5059}
5160
52const LessThanContext = struct { ty: Type, module: *Module };
53
5461/// Assumes a and b do not overlap
55fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {
56 return a.first.compareAll(.lt, b.first, ctx.ty, ctx.module);
62fn lessThan(mod: *Module, a: Range, b: Range) bool {
63 const ty = mod.intern_pool.typeOf(a.first).toType();
64 return a.first.toValue().compareScalar(.lt, b.first.toValue(), ty, mod);
5765}
5866
59pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
67pub fn spans(self: *RangeSet, first: InternPool.Index, last: InternPool.Index) !bool {
68 const mod = self.module;
69 const ip = &mod.intern_pool;
70 assert(ip.typeOf(first) == ip.typeOf(last));
71
6072 if (self.ranges.items.len == 0)
6173 return false;
6274
63 std.mem.sort(Range, self.ranges.items, LessThanContext{
64 .ty = ty,
65 .module = self.module,
66 }, lessThan);
75 std.mem.sort(Range, self.ranges.items, mod, lessThan);
6776
68 if (!self.ranges.items[0].first.eql(first, ty, self.module) or
69 !self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, self.module))
77 if (self.ranges.items[0].first != first or
78 self.ranges.items[self.ranges.items.len - 1].last != last)
7079 {
7180 return false;
7281 }
7382
74 var space: Value.BigIntSpace = undefined;
83 var space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
7584
7685 var counter = try std.math.big.int.Managed.init(self.ranges.allocator);
7786 defer counter.deinit();
7887
79 const target = self.module.getTarget();
80
8188 // look for gaps
8289 for (self.ranges.items[1..], 0..) |cur, i| {
8390 // i starts counting from the second item.
8491 const prev = self.ranges.items[i];
8592
8693 // prev.last + 1 == cur.first
87 try counter.copy(prev.last.toBigInt(&space, target));
94 try counter.copy(prev.last.toValue().toBigInt(&space, mod));
8895 try counter.addScalar(&counter, 1);
8996
90 const cur_start_int = cur.first.toBigInt(&space, target);
97 const cur_start_int = cur.first.toValue().toBigInt(&space, mod);
9198 if (!cur_start_int.eq(counter.toConst())) {
9299 return false;
93100 }
src/Sema.zig+8816-8097
......@@ -11,13 +11,9 @@ gpa: Allocator,
1111/// Points to the temporary arena allocator of the Sema.
1212/// This arena will be cleared when the sema is destroyed.
1313arena: Allocator,
14/// Points to the arena allocator for the owner_decl.
15/// This arena will persist until the decl is invalidated.
16perm_arena: Allocator,
1714code: Zir,
1815air_instructions: std.MultiArrayList(Air.Inst) = .{},
1916air_extra: std.ArrayListUnmanaged(u32) = .{},
20air_values: std.ArrayListUnmanaged(Value) = .{},
2117/// Maps ZIR to AIR.
2218inst_map: InstMap = .{},
2319/// When analyzing an inline function call, owner_decl is the Decl of the caller
......@@ -28,10 +24,12 @@ owner_decl_index: Decl.Index,
2824/// For an inline or comptime function call, this will be the root parent function
2925/// which contains the callsite. Corresponds to `owner_decl`.
3026owner_func: ?*Module.Fn,
27owner_func_index: Module.Fn.OptionalIndex,
3128/// The function this ZIR code is the body of, according to the source code.
3229/// This starts out the same as `owner_func` and then diverges in the case of
3330/// an inline or comptime function call.
3431func: ?*Module.Fn,
32func_index: Module.Fn.OptionalIndex,
3533/// Used to restore the error return trace when returning a non-error from a function.
3634error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3735/// When semantic analysis needs to know the return type of the function whose body
......@@ -65,12 +63,15 @@ comptime_args_fn_inst: Zir.Inst.Index = 0,
6563/// to use this instead of allocating a fresh one. This avoids an unnecessary
6664/// extra hash table lookup in the `monomorphed_funcs` set.
6765/// Sema will set this to null when it takes ownership.
68preallocated_new_func: ?*Module.Fn = null,
69/// The key is `constant` AIR instructions to types that must be fully resolved
70/// after the current function body analysis is done.
71/// TODO: after upgrading to use InternPool change the key here to be an
72/// InternPool value index.
73types_to_resolve: std.ArrayListUnmanaged(Air.Inst.Ref) = .{},
66preallocated_new_func: Module.Fn.OptionalIndex = .none,
67/// The key is types that must be fully resolved prior to machine code
68/// generation pass. Types are added to this set when resolving them
69/// immediately could cause a dependency loop, but they do need to be resolved
70/// before machine code generation passes process the AIR.
71/// It would work fine if this were an array list instead of an array hash map.
72/// I chose array hash map with the intention to save time by omitting
73/// duplicates.
74types_to_resolve: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{},
7475/// These are lazily created runtime blocks from block_inline instructions.
7576/// They are created when an break_inline passes through a runtime condition, because
7677/// Sema must convert comptime control flow to runtime control flow, which means
......@@ -84,12 +85,22 @@ is_generic_instantiation: bool = false,
8485/// function types will emit generic poison instead of a partial type.
8586no_partial_func_ty: bool = false,
8687
87unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, void) = .{},
88/// The temporary arena is used for the memory of the `InferredAlloc` values
89/// here so the values can be dropped without any cleanup.
90unresolved_inferred_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{},
91
92/// Indices of comptime-mutable decls created by this Sema. These decls' values
93/// should be interned after analysis completes, as they may refer to memory in
94/// the Sema arena.
95/// TODO: this is a workaround for memory bugs triggered by the removal of
96/// Decl.value_arena. A better solution needs to be found. Probably this will
97/// involve transitioning comptime-mutable memory away from using Decls at all.
98comptime_mutable_decls: *std.ArrayList(Decl.Index),
8899
89100const std = @import("std");
90101const math = std.math;
91102const mem = std.mem;
92const Allocator = std.mem.Allocator;
103const Allocator = mem.Allocator;
93104const assert = std.debug.assert;
94105const log = std.log.scoped(.sema);
95106
......@@ -114,6 +125,7 @@ const Package = @import("Package.zig");
114125const crash_report = @import("crash_report.zig");
115126const build_options = @import("build_options");
116127const Compilation = @import("Compilation.zig");
128const InternPool = @import("InternPool.zig");
117129
118130pub const default_branch_quota = 1000;
119131pub const default_reference_trace_len = 2;
......@@ -226,7 +238,7 @@ pub const Block = struct {
226238 sema: *Sema,
227239 /// The namespace to use for lookups from this source block
228240 /// When analyzing fields, this is different from src_decl.src_namespace.
229 namespace: *Namespace,
241 namespace: Namespace.Index,
230242 /// The AIR instructions generated for this block.
231243 instructions: std.ArrayListUnmanaged(Air.Inst.Index),
232244 // `param` instructions are collected here to be used by the `func` instruction.
......@@ -285,6 +297,7 @@ pub const Block = struct {
285297
286298 fn explain(cr: ComptimeReason, sema: *Sema, msg: ?*Module.ErrorMsg) !void {
287299 const parent = msg orelse return;
300 const mod = sema.mod;
288301 const prefix = "expression is evaluated at comptime because ";
289302 switch (cr) {
290303 .c_import => |ci| {
......@@ -292,21 +305,21 @@ pub const Block = struct {
292305 },
293306 .comptime_ret_ty => |rt| {
294307 const src_loc = if (try sema.funcDeclSrc(rt.func)) |fn_decl| blk: {
295 var src_loc = fn_decl.srcLoc();
308 var src_loc = fn_decl.srcLoc(mod);
296309 src_loc.lazy = .{ .node_offset_fn_type_ret_ty = 0 };
297310 break :blk src_loc;
298311 } else blk: {
299 const src_decl = sema.mod.declPtr(rt.block.src_decl);
300 break :blk rt.func_src.toSrcLoc(src_decl);
312 const src_decl = mod.declPtr(rt.block.src_decl);
313 break :blk rt.func_src.toSrcLoc(src_decl, mod);
301314 };
302 if (rt.return_ty.tag() == .generic_poison) {
303 return sema.mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{});
315 if (rt.return_ty.isGenericPoison()) {
316 return mod.errNoteNonLazy(src_loc, parent, prefix ++ "the generic function was instantiated with a comptime-only return type", .{});
304317 }
305 try sema.mod.errNoteNonLazy(
318 try mod.errNoteNonLazy(
306319 src_loc,
307320 parent,
308321 prefix ++ "the function returns a comptime-only type '{}'",
309 .{rt.return_ty.fmt(sema.mod)},
322 .{rt.return_ty.fmt(mod)},
310323 );
311324 try sema.explainWhyTypeIsComptime(parent, src_loc, rt.return_ty);
312325 },
......@@ -398,8 +411,8 @@ pub const Block = struct {
398411 };
399412 }
400413
401 pub fn getFileScope(block: *Block) *Module.File {
402 return block.namespace.file_scope;
414 pub fn getFileScope(block: *Block, mod: *Module) *Module.File {
415 return mod.namespacePtr(block.namespace).file_scope;
403416 }
404417
405418 fn addTy(
......@@ -584,13 +597,18 @@ pub const Block = struct {
584597 }
585598
586599 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator) !Air.Inst.Ref {
600 const sema = block.sema;
601 const mod = sema.mod;
587602 return block.addInst(.{
588603 .tag = if (block.float_mode == .Optimized) .cmp_vector_optimized else .cmp_vector,
589604 .data = .{ .ty_pl = .{
590 .ty = try block.sema.addType(
591 try Type.vector(block.sema.arena, block.sema.typeOf(lhs).vectorLen(), Type.bool),
605 .ty = try sema.addType(
606 try mod.vectorType(.{
607 .len = sema.typeOf(lhs).vectorLen(mod),
608 .child = .bool_type,
609 }),
592610 ),
593 .payload = try block.sema.addExtra(Air.VectorCmp{
611 .payload = try sema.addExtra(Air.VectorCmp{
594612 .lhs = lhs,
595613 .rhs = rhs,
596614 .op = Air.VectorCmp.encodeOp(cmp_op),
......@@ -684,29 +702,20 @@ pub const Block = struct {
684702 pub fn startAnonDecl(block: *Block) !WipAnonDecl {
685703 return WipAnonDecl{
686704 .block = block,
687 .new_decl_arena = std.heap.ArenaAllocator.init(block.sema.gpa),
688705 .finished = false,
689706 };
690707 }
691708
692709 pub const WipAnonDecl = struct {
693710 block: *Block,
694 new_decl_arena: std.heap.ArenaAllocator,
695711 finished: bool,
696712
697 pub fn arena(wad: *WipAnonDecl) Allocator {
698 return wad.new_decl_arena.allocator();
699 }
700
701713 pub fn deinit(wad: *WipAnonDecl) void {
702 if (!wad.finished) {
703 wad.new_decl_arena.deinit();
704 }
705714 wad.* = undefined;
706715 }
707716
708717 /// `alignment` value of 0 means to use ABI alignment.
709 pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u32) !Decl.Index {
718 pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u64) !Decl.Index {
710719 const sema = wad.block.sema;
711720 // Do this ahead of time because `createAnonymousDecl` depends on calling
712721 // `type.hasRuntimeBits()`.
......@@ -716,10 +725,11 @@ pub const Block = struct {
716725 .val = val,
717726 });
718727 const new_decl = sema.mod.declPtr(new_decl_index);
719 new_decl.@"align" = alignment;
728 // TODO: migrate Decl alignment to use `InternPool.Alignment`
729 new_decl.@"align" = @intCast(u32, alignment);
720730 errdefer sema.mod.abortAnonDecl(new_decl_index);
721 try new_decl.finalizeNewArena(&wad.new_decl_arena);
722731 wad.finished = true;
732 try sema.mod.finalizeAnonDecl(new_decl_index);
723733 return new_decl_index;
724734 }
725735 };
......@@ -736,11 +746,27 @@ const LabeledBlock = struct {
736746 }
737747};
738748
749/// The value stored in the inferred allocation. This will go into
750/// peer type resolution. This is stored in a separate list so that
751/// the items are contiguous in memory and thus can be passed to
752/// `Module.resolvePeerTypes`.
753const InferredAlloc = struct {
754 prongs: std.MultiArrayList(struct {
755 /// The dummy instruction used as a peer to resolve the type.
756 /// Although this has a redundant type with placeholder, this is
757 /// needed in addition because it may be a constant value, which
758 /// affects peer type resolution.
759 stored_inst: Air.Inst.Ref,
760 /// The bitcast instruction used as a placeholder when the
761 /// new result pointer type is not yet known.
762 placeholder: Air.Inst.Index,
763 }) = .{},
764};
765
739766pub fn deinit(sema: *Sema) void {
740767 const gpa = sema.gpa;
741768 sema.air_instructions.deinit(gpa);
742769 sema.air_extra.deinit(gpa);
743 sema.air_values.deinit(gpa);
744770 sema.inst_map.deinit(gpa);
745771 sema.decl_val_table.deinit(gpa);
746772 sema.types_to_resolve.deinit(gpa);
......@@ -823,7 +849,7 @@ pub fn analyzeBodyBreak(
823849 else => |e| return e,
824850 };
825851 if (block.instructions.items.len != 0 and
826 sema.typeOf(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])).isNoReturn())
852 sema.isNoReturn(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])))
827853 return null;
828854 const break_data = sema.code.instructions.items(.data)[break_inst].@"break";
829855 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data;
......@@ -858,18 +884,20 @@ fn analyzeBodyInner(
858884
859885 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body);
860886
887 // Most of the time, we don't need to construct a new capture scope for a
888 // block. However, successive iterations of comptime loops can capture
889 // different values for the same Zir.Inst.Index, so in those cases, we will
890 // have to create nested capture scopes; see the `.repeat` case below.
861891 const parent_capture_scope = block.wip_capture_scope;
862
863 var wip_captures = WipCaptureScope{
864 .finalized = true,
892 parent_capture_scope.incRef();
893 var wip_captures: WipCaptureScope = .{
865894 .scope = parent_capture_scope,
866 .perm_arena = sema.perm_arena,
867895 .gpa = sema.gpa,
896 .finalized = true, // don't finalize the parent scope
868897 };
869 defer if (wip_captures.scope != parent_capture_scope) {
870 wip_captures.deinit();
871 };
898 defer wip_captures.deinit();
872899
900 const mod = sema.mod;
873901 const map = &sema.inst_map;
874902 const tags = sema.code.instructions.items(.tag);
875903 const datas = sema.code.instructions.items(.data);
......@@ -890,15 +918,15 @@ fn analyzeBodyInner(
890918 crash_info.setBodyIndex(i);
891919 const inst = body[i];
892920 std.log.scoped(.sema_zir).debug("sema ZIR {s} %{d}", .{
893 sema.mod.declPtr(block.src_decl).src_namespace.file_scope.sub_file_path, inst,
921 mod.namespacePtr(mod.declPtr(block.src_decl).src_namespace).file_scope.sub_file_path, inst,
894922 });
895923 const air_inst: Air.Inst.Ref = switch (tags[inst]) {
896924 // zig fmt: off
897925 .alloc => try sema.zirAlloc(block, inst),
898 .alloc_inferred => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_const)),
899 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, Type.initTag(.inferred_alloc_mut)),
900 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, Type.initTag(.inferred_alloc_const)),
901 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, Type.initTag(.inferred_alloc_mut)),
926 .alloc_inferred => try sema.zirAllocInferred(block, inst, true),
927 .alloc_inferred_mut => try sema.zirAllocInferred(block, inst, false),
928 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(inst, true),
929 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(inst, false),
902930 .alloc_mut => try sema.zirAllocMut(block, inst),
903931 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst),
904932 .make_ptr_const => try sema.zirMakePtrConst(block, inst),
......@@ -962,7 +990,7 @@ fn analyzeBodyInner(
962990 .int_big => try sema.zirIntBig(block, inst),
963991 .float => try sema.zirFloat(block, inst),
964992 .float128 => try sema.zirFloat128(block, inst),
965 .int_type => try sema.zirIntType(block, inst),
993 .int_type => try sema.zirIntType(inst),
966994 .is_non_err => try sema.zirIsNonErr(block, inst),
967995 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst),
968996 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst),
......@@ -1420,6 +1448,11 @@ fn analyzeBodyInner(
14201448 const src = LazySrcLoc.nodeOffset(datas[inst].node);
14211449 try sema.emitBackwardBranch(block, src);
14221450 if (wip_captures.scope.captures.count() != orig_captures) {
1451 // We need to construct new capture scopes for the next loop iteration so it
1452 // can capture values without clobbering the earlier iteration's captures.
1453 // At first, we reused the parent capture scope as an optimization, but for
1454 // successive scopes we have to create new ones as children of the parent
1455 // scope.
14231456 try wip_captures.reset(parent_capture_scope);
14241457 block.wip_capture_scope = wip_captures.scope;
14251458 orig_captures = 0;
......@@ -1435,6 +1468,11 @@ fn analyzeBodyInner(
14351468 const src = LazySrcLoc.nodeOffset(datas[inst].node);
14361469 try sema.emitBackwardBranch(block, src);
14371470 if (wip_captures.scope.captures.count() != orig_captures) {
1471 // We need to construct new capture scopes for the next loop iteration so it
1472 // can capture values without clobbering the earlier iteration's captures.
1473 // At first, we reused the parent capture scope as an optimization, but for
1474 // successive scopes we have to create new ones as children of the parent
1475 // scope.
14381476 try wip_captures.reset(parent_capture_scope);
14391477 block.wip_capture_scope = wip_captures.scope;
14401478 orig_captures = 0;
......@@ -1621,18 +1659,18 @@ fn analyzeBodyInner(
16211659 const inline_body = sema.code.extra[extra.end..][0..extra.data.body_len];
16221660 const err_union = try sema.resolveInst(extra.data.operand);
16231661 const err_union_ty = sema.typeOf(err_union);
1624 if (err_union_ty.zigTypeTag() != .ErrorUnion) {
1662 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) {
16251663 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{
1626 err_union_ty.fmt(sema.mod),
1664 err_union_ty.fmt(mod),
16271665 });
16281666 }
16291667 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
16301668 assert(is_non_err != .none);
1631 const is_non_err_tv = sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| {
1669 const is_non_err_val = sema.resolveConstValue(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| {
16321670 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
16331671 return err;
16341672 };
1635 if (is_non_err_tv.val.toBool()) {
1673 if (is_non_err_val.toBool()) {
16361674 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false);
16371675 }
16381676 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
......@@ -1654,11 +1692,11 @@ fn analyzeBodyInner(
16541692 const err_union = try sema.analyzeLoad(block, src, operand, operand_src);
16551693 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, operand_src, err_union);
16561694 assert(is_non_err != .none);
1657 const is_non_err_tv = sema.resolveInstConst(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| {
1695 const is_non_err_val = sema.resolveConstValue(block, operand_src, is_non_err, "try operand inside comptime block must be comptime-known") catch |err| {
16581696 if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err);
16591697 return err;
16601698 };
1661 if (is_non_err_tv.val.toBool()) {
1699 if (is_non_err_val.toBool()) {
16621700 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false);
16631701 }
16641702 const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse
......@@ -1684,7 +1722,7 @@ fn analyzeBodyInner(
16841722 const extra = sema.code.extraData(Zir.Inst.DeferErrCode, inst_data.payload_index).data;
16851723 const defer_body = sema.code.extra[extra.index..][0..extra.len];
16861724 const err_code = try sema.resolveInst(inst_data.err_code);
1687 sema.inst_map.putAssumeCapacity(extra.remapped_err_code, err_code);
1725 map.putAssumeCapacity(extra.remapped_err_code, err_code);
16881726 const break_inst = sema.analyzeBodyInner(block, defer_body) catch |err| switch (err) {
16891727 error.ComptimeBreak => sema.comptime_break_inst,
16901728 else => |e| return e,
......@@ -1693,8 +1731,12 @@ fn analyzeBodyInner(
16931731 break :blk Air.Inst.Ref.void_value;
16941732 },
16951733 };
1696 if (sema.typeOf(air_inst).isNoReturn())
1734 if (sema.isNoReturn(air_inst)) {
1735 // We're going to assume that the body itself is noreturn, so let's ensure that now
1736 assert(block.instructions.items.len > 0);
1737 assert(sema.isNoReturn(Air.indexToRef(block.instructions.items[block.instructions.items.len - 1])));
16971738 break always_noreturn;
1739 }
16981740 map.putAssumeCapacity(inst, air_inst);
16991741 i += 1;
17001742 };
......@@ -1703,7 +1745,7 @@ fn analyzeBodyInner(
17031745 const noreturn_inst = block.instructions.popOrNull();
17041746 while (dbg_block_begins > 0) {
17051747 dbg_block_begins -= 1;
1706 if (block.is_comptime or sema.mod.comp.bin_file.options.strip) continue;
1748 if (block.is_comptime or mod.comp.bin_file.options.strip) continue;
17071749
17081750 _ = try block.addInst(.{
17091751 .tag = .dbg_block_end,
......@@ -1713,6 +1755,8 @@ fn analyzeBodyInner(
17131755 if (noreturn_inst) |some| try block.instructions.append(sema.gpa, some);
17141756
17151757 if (!wip_captures.finalized) {
1758 // We've updated the capture scope due to a `repeat` instruction where
1759 // the body had a capture; finalize our child scope and reset
17161760 try wip_captures.finalize();
17171761 block.wip_capture_scope = parent_capture_scope;
17181762 }
......@@ -1720,20 +1764,23 @@ fn analyzeBodyInner(
17201764 return result;
17211765}
17221766
1723pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1724 var i: usize = @enumToInt(zir_ref);
1725
1726 // First section of indexes correspond to a set number of constant values.
1727 if (i < Zir.Inst.Ref.typed_value_map.len) {
1728 // We intentionally map the same indexes to the same values between ZIR and AIR.
1729 return zir_ref;
1767pub fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1768 if (zir_ref == .none) {
1769 return .none;
1770 } else {
1771 return resolveInst(sema, zir_ref);
17301772 }
1731 i -= Zir.Inst.Ref.typed_value_map.len;
1773}
17321774
1733 // Finally, the last section of indexes refers to the map of ZIR=>AIR.
1734 const inst = sema.inst_map.get(@intCast(u32, i)).?;
1735 const ty = sema.typeOf(inst);
1736 if (ty.tag() == .generic_poison) return error.GenericPoison;
1775pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) !Air.Inst.Ref {
1776 assert(zir_ref != .none);
1777 const i = @enumToInt(zir_ref);
1778 // First section of indexes correspond to a set number of constant values.
1779 // We intentionally map the same indexes to the same values between ZIR and AIR.
1780 if (i < InternPool.static_len) return @intToEnum(Air.Inst.Ref, i);
1781 // The last section of indexes refers to the map of ZIR => AIR.
1782 const inst = sema.inst_map.get(i - InternPool.static_len).?;
1783 if (inst == .generic_poison) return error.GenericPoison;
17371784 return inst;
17381785}
17391786
......@@ -1759,18 +1806,31 @@ pub fn resolveConstString(
17591806 reason: []const u8,
17601807) ![]u8 {
17611808 const air_inst = try sema.resolveInst(zir_ref);
1762 const wanted_type = Type.initTag(.const_slice_u8);
1809 const wanted_type = Type.slice_const_u8;
17631810 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
17641811 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
17651812 return val.toAllocatedBytes(wanted_type, sema.arena, sema.mod);
17661813}
17671814
1815pub fn resolveConstStringIntern(
1816 sema: *Sema,
1817 block: *Block,
1818 src: LazySrcLoc,
1819 zir_ref: Zir.Inst.Ref,
1820 reason: []const u8,
1821) !InternPool.NullTerminatedString {
1822 const air_inst = try sema.resolveInst(zir_ref);
1823 const wanted_type = Type.slice_const_u8;
1824 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
1825 const val = try sema.resolveConstValue(block, src, coerced_inst, reason);
1826 return val.toIpString(wanted_type, sema.mod);
1827}
1828
17681829pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type {
1769 assert(zir_ref != .var_args_param);
17701830 const air_inst = try sema.resolveInst(zir_ref);
1771 assert(air_inst != .var_args_param);
1831 assert(air_inst != .var_args_param_type);
17721832 const ty = try sema.analyzeAsType(block, src, air_inst);
1773 if (ty.tag() == .generic_poison) return error.GenericPoison;
1833 if (ty.isGenericPoison()) return error.GenericPoison;
17741834 return ty;
17751835}
17761836
......@@ -1780,45 +1840,48 @@ fn analyzeAsType(
17801840 src: LazySrcLoc,
17811841 air_inst: Air.Inst.Ref,
17821842) !Type {
1783 const wanted_type = Type.initTag(.type);
1843 const wanted_type = Type.type;
17841844 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src);
17851845 const val = try sema.resolveConstValue(block, src, coerced_inst, "types must be comptime-known");
1786 var buffer: Value.ToTypeBuffer = undefined;
1787 const ty = val.toType(&buffer);
1788 return ty.copy(sema.arena);
1846 return val.toType();
17891847}
17901848
17911849pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void {
1792 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
1850 const mod = sema.mod;
1851 const gpa = sema.gpa;
1852 const ip = &mod.intern_pool;
1853 if (!mod.backendSupportsFeature(.error_return_trace)) return;
17931854
17941855 assert(!block.is_comptime);
17951856 var err_trace_block = block.makeSubBlock();
1796 defer err_trace_block.instructions.deinit(sema.gpa);
1857 defer err_trace_block.instructions.deinit(gpa);
17971858
17981859 const src: LazySrcLoc = .unneeded;
17991860
18001861 // var addrs: [err_return_trace_addr_count]usize = undefined;
18011862 const err_return_trace_addr_count = 32;
1802 const addr_arr_ty = try Type.array(sema.arena, err_return_trace_addr_count, null, Type.usize, sema.mod);
1803 const addrs_ptr = try err_trace_block.addTy(.alloc, try Type.Tag.single_mut_pointer.create(sema.arena, addr_arr_ty));
1863 const addr_arr_ty = try Type.array(sema.arena, err_return_trace_addr_count, null, Type.usize, mod);
1864 const addrs_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(addr_arr_ty));
18041865
18051866 // var st: StackTrace = undefined;
18061867 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
18071868 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
1808 const st_ptr = try err_trace_block.addTy(.alloc, try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty));
1869 const st_ptr = try err_trace_block.addTy(.alloc, try mod.singleMutPtrType(stack_trace_ty));
18091870
18101871 // st.instruction_addresses = &addrs;
1811 const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, "instruction_addresses", src, true);
1872 const instruction_addresses_field_name = try ip.getOrPutString(gpa, "instruction_addresses");
1873 const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true);
18121874 try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);
18131875
18141876 // st.index = 0;
1815 const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, "index", src, true);
1877 const index_field_name = try ip.getOrPutString(gpa, "index");
1878 const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true);
18161879 try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store);
18171880
18181881 // @errorReturnTrace() = &st;
18191882 _ = try err_trace_block.addUnOp(.set_err_return_trace, st_ptr);
18201883
1821 try block.instructions.insertSlice(sema.gpa, last_arg_index, err_trace_block.instructions.items);
1884 try block.instructions.insertSlice(gpa, last_arg_index, err_trace_block.instructions.items);
18221885}
18231886
18241887/// May return Value Tags: `variable`, `undef`.
......@@ -1832,7 +1895,7 @@ fn resolveValue(
18321895 reason: []const u8,
18331896) CompileError!Value {
18341897 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
1835 if (val.tag() == .generic_poison) return error.GenericPoison;
1898 if (val.isGenericPoison()) return error.GenericPoison;
18361899 return val;
18371900 }
18381901 return sema.failWithNeededComptime(block, src, reason);
......@@ -1848,10 +1911,12 @@ fn resolveConstMaybeUndefVal(
18481911 reason: []const u8,
18491912) CompileError!Value {
18501913 if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| {
1851 switch (val.tag()) {
1852 .variable => return sema.failWithNeededComptime(block, src, reason),
1914 switch (val.toIntern()) {
18531915 .generic_poison => return error.GenericPoison,
1854 else => return val,
1916 else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
1917 .variable => return sema.failWithNeededComptime(block, src, reason),
1918 else => return val,
1919 },
18551920 }
18561921 }
18571922 return sema.failWithNeededComptime(block, src, reason);
......@@ -1867,16 +1932,31 @@ fn resolveConstValue(
18671932 reason: []const u8,
18681933) CompileError!Value {
18691934 if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| {
1870 switch (val.tag()) {
1871 .undef => return sema.failWithUseOfUndef(block, src),
1872 .variable => return sema.failWithNeededComptime(block, src, reason),
1935 switch (val.toIntern()) {
18731936 .generic_poison => return error.GenericPoison,
1874 else => return val,
1937 .undef => return sema.failWithUseOfUndef(block, src),
1938 else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
1939 .undef => return sema.failWithUseOfUndef(block, src),
1940 .variable => return sema.failWithNeededComptime(block, src, reason),
1941 else => return val,
1942 },
18751943 }
18761944 }
18771945 return sema.failWithNeededComptime(block, src, reason);
18781946}
18791947
1948/// Will not return Value Tags: `variable`, `undef`. Instead they will emit compile errors.
1949/// Lazy values are recursively resolved.
1950fn resolveConstLazyValue(
1951 sema: *Sema,
1952 block: *Block,
1953 src: LazySrcLoc,
1954 air_ref: Air.Inst.Ref,
1955 reason: []const u8,
1956) CompileError!Value {
1957 return sema.resolveLazyValue(try sema.resolveConstValue(block, src, air_ref, reason));
1958}
1959
18801960/// Value Tag `variable` causes this function to return `null`.
18811961/// Value Tag `undef` causes this function to return a compile error.
18821962fn resolveDefinedValue(
......@@ -1885,8 +1965,9 @@ fn resolveDefinedValue(
18851965 src: LazySrcLoc,
18861966 air_ref: Air.Inst.Ref,
18871967) CompileError!?Value {
1968 const mod = sema.mod;
18881969 if (try sema.resolveMaybeUndefVal(air_ref)) |val| {
1889 if (val.isUndef()) {
1970 if (val.isUndef(mod)) {
18901971 if (block.is_typeof) return null;
18911972 return sema.failWithUseOfUndef(block, src);
18921973 }
......@@ -1903,34 +1984,53 @@ fn resolveMaybeUndefVal(
19031984 inst: Air.Inst.Ref,
19041985) CompileError!?Value {
19051986 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
1906 switch (val.tag()) {
1907 .variable => return null,
1987 switch (val.ip_index) {
19081988 .generic_poison => return error.GenericPoison,
1909 else => return val,
1989 .none => return val,
1990 else => switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
1991 .variable => return null,
1992 else => return val,
1993 },
19101994 }
19111995}
19121996
1997/// Value Tag `variable` causes this function to return `null`.
1998/// Value Tag `undef` causes this function to return the Value.
1999/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
2000/// Lazy values are recursively resolved.
2001fn resolveMaybeUndefLazyVal(
2002 sema: *Sema,
2003 inst: Air.Inst.Ref,
2004) CompileError!?Value {
2005 return try sema.resolveLazyValue((try sema.resolveMaybeUndefVal(inst)) orelse return null);
2006}
2007
19132008/// Value Tag `variable` results in `null`.
19142009/// Value Tag `undef` results in the Value.
19152010/// Value Tag `generic_poison` causes `error.GenericPoison` to be returned.
19162011/// Value Tag `decl_ref` and `decl_ref_mut` or any nested such value results in `null`.
2012/// Lazy values are recursively resolved.
19172013fn resolveMaybeUndefValIntable(
19182014 sema: *Sema,
19192015 inst: Air.Inst.Ref,
19202016) CompileError!?Value {
19212017 const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null;
19222018 var check = val;
1923 while (true) switch (check.tag()) {
1924 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return null,
1925 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,
1926 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
1927 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
2019 while (true) switch (check.ip_index) {
19282020 .generic_poison => return error.GenericPoison,
1929 else => {
1930 try sema.resolveLazyValue(val);
1931 return val;
2021 .none => break,
2022 else => switch (sema.mod.intern_pool.indexToKey(check.toIntern())) {
2023 .variable => return null,
2024 .ptr => |ptr| switch (ptr.addr) {
2025 .decl, .mut_decl, .comptime_field => return null,
2026 .int => break,
2027 .eu_payload, .opt_payload => |base| check = base.toValue(),
2028 .elem, .field => |base_index| check = base_index.base.toValue(),
2029 },
2030 else => break,
19322031 },
19332032 };
2033 return try sema.resolveLazyValue(val);
19342034}
19352035
19362036/// Returns all Value tags including `variable` and `undef`.
......@@ -1949,35 +2049,33 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
19492049 inst: Air.Inst.Ref,
19502050 make_runtime: *bool,
19512051) CompileError!?Value {
2052 assert(inst != .none);
19522053 // First section of indexes correspond to a set number of constant values.
1953 var i: usize = @enumToInt(inst);
1954 if (i < Air.Inst.Ref.typed_value_map.len) {
1955 return Air.Inst.Ref.typed_value_map[i].val;
2054 const int = @enumToInt(inst);
2055 if (int < InternPool.static_len) {
2056 return @intToEnum(InternPool.Index, int).toValue();
19562057 }
1957 i -= Air.Inst.Ref.typed_value_map.len;
19582058
2059 const i = int - InternPool.static_len;
19592060 const air_tags = sema.air_instructions.items(.tag);
19602061 if (try sema.typeHasOnePossibleValue(sema.typeOf(inst))) |opv| {
1961 if (air_tags[i] == .constant) {
1962 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
1963 const val = sema.air_values.items[ty_pl.payload];
1964 if (val.tag() == .variable) return val;
2062 if (air_tags[i] == .interned) {
2063 const interned = sema.air_instructions.items(.data)[i].interned;
2064 const val = interned.toValue();
2065 if (val.getVariable(sema.mod) != null) return val;
19652066 }
19662067 return opv;
19672068 }
1968 switch (air_tags[i]) {
1969 .constant => {
1970 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
1971 const val = sema.air_values.items[ty_pl.payload];
1972 if (val.tag() == .runtime_value) make_runtime.* = true;
1973 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
1974 return val;
1975 },
1976 .const_ty => {
1977 return try sema.air_instructions.items(.data)[i].ty.toValue(sema.arena);
1978 },
2069 const air_datas = sema.air_instructions.items(.data);
2070 const val = switch (air_tags[i]) {
2071 .inferred_alloc => unreachable,
2072 .inferred_alloc_comptime => unreachable,
2073 .interned => air_datas[i].interned.toValue(),
19792074 else => return null,
1980 }
2075 };
2076 if (val.isRuntimeValue(sema.mod)) make_runtime.* = true;
2077 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
2078 return val;
19812079}
19822080
19832081fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: []const u8) CompileError {
......@@ -2010,13 +2108,14 @@ fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, opt
20102108}
20112109
20122110fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError {
2111 const mod = sema.mod;
20132112 const msg = msg: {
20142113 const msg = try sema.errMsg(block, src, "type '{}' does not support array initialization syntax", .{
2015 ty.fmt(sema.mod),
2114 ty.fmt(mod),
20162115 });
20172116 errdefer msg.destroy(sema.gpa);
2018 if (ty.isSlice()) {
2019 try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2().fmt(sema.mod)});
2117 if (ty.isSlice(mod)) {
2118 try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)});
20202119 }
20212120 break :msg msg;
20222121 };
......@@ -2042,7 +2141,8 @@ fn failWithErrorSetCodeMissing(
20422141}
20432142
20442143fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: usize) CompileError {
2045 if (int_ty.zigTypeTag() == .Vector) {
2144 const mod = sema.mod;
2145 if (int_ty.zigTypeTag(mod) == .Vector) {
20462146 const msg = msg: {
20472147 const msg = try sema.errMsg(block, src, "overflow of vector type '{}' with value '{}'", .{
20482148 int_ty.fmt(sema.mod), val.fmtValue(int_ty, sema.mod),
......@@ -2059,16 +2159,17 @@ fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty:
20592159}
20602160
20612161fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError {
2162 const mod = sema.mod;
20622163 const msg = msg: {
20632164 const msg = try sema.errMsg(block, init_src, "value stored in comptime field does not match the default value of the field", .{});
20642165 errdefer msg.destroy(sema.gpa);
20652166
2066 const struct_ty = container_ty.castTag(.@"struct") orelse break :msg msg;
2067 const default_value_src = struct_ty.data.fieldSrcLoc(sema.mod, .{
2167 const struct_ty = mod.typeToStruct(container_ty) orelse break :msg msg;
2168 const default_value_src = mod.fieldSrcLoc(struct_ty.owner_decl, .{
20682169 .index = field_index,
20692170 .range = .value,
20702171 });
2071 try sema.mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
2172 try mod.errNoteNonLazy(default_value_src, msg, "default value set here", .{});
20722173 break :msg msg;
20732174 };
20742175 return sema.failWithOwnedErrorMsg(msg);
......@@ -2083,13 +2184,19 @@ fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError
20832184 return sema.failWithOwnedErrorMsg(msg);
20842185}
20852186
2086fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, object_ty: Type, field_name: []const u8) CompileError {
2087 const inner_ty = if (object_ty.isSinglePointer()) object_ty.childType() else object_ty;
2187fn failWithInvalidFieldAccess(
2188 sema: *Sema,
2189 block: *Block,
2190 src: LazySrcLoc,
2191 object_ty: Type,
2192 field_name: InternPool.NullTerminatedString,
2193) CompileError {
2194 const mod = sema.mod;
2195 const inner_ty = if (object_ty.isSinglePointer(mod)) object_ty.childType(mod) else object_ty;
20882196
2089 if (inner_ty.zigTypeTag() == .Optional) opt: {
2090 var buf: Type.Payload.ElemType = undefined;
2091 const child_ty = inner_ty.optionalChild(&buf);
2092 if (!typeSupportsFieldAccess(child_ty, field_name)) break :opt;
2197 if (inner_ty.zigTypeTag(mod) == .Optional) opt: {
2198 const child_ty = inner_ty.optionalChild(mod);
2199 if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :opt;
20932200 const msg = msg: {
20942201 const msg = try sema.errMsg(block, src, "optional type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
20952202 errdefer msg.destroy(sema.gpa);
......@@ -2097,9 +2204,9 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec
20972204 break :msg msg;
20982205 };
20992206 return sema.failWithOwnedErrorMsg(msg);
2100 } else if (inner_ty.zigTypeTag() == .ErrorUnion) err: {
2101 const child_ty = inner_ty.errorUnionPayload();
2102 if (!typeSupportsFieldAccess(child_ty, field_name)) break :err;
2207 } else if (inner_ty.zigTypeTag(mod) == .ErrorUnion) err: {
2208 const child_ty = inner_ty.errorUnionPayload(mod);
2209 if (!typeSupportsFieldAccess(mod, child_ty, field_name)) break :err;
21032210 const msg = msg: {
21042211 const msg = try sema.errMsg(block, src, "error union type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
21052212 errdefer msg.destroy(sema.gpa);
......@@ -2111,15 +2218,16 @@ fn failWithInvalidFieldAccess(sema: *Sema, block: *Block, src: LazySrcLoc, objec
21112218 return sema.fail(block, src, "type '{}' does not support field access", .{object_ty.fmt(sema.mod)});
21122219}
21132220
2114fn typeSupportsFieldAccess(ty: Type, field_name: []const u8) bool {
2115 switch (ty.zigTypeTag()) {
2116 .Array => return mem.eql(u8, field_name, "len"),
2221fn typeSupportsFieldAccess(mod: *const Module, ty: Type, field_name: InternPool.NullTerminatedString) bool {
2222 const ip = &mod.intern_pool;
2223 switch (ty.zigTypeTag(mod)) {
2224 .Array => return ip.stringEqlSlice(field_name, "len"),
21172225 .Pointer => {
2118 const ptr_info = ty.ptrInfo().data;
2226 const ptr_info = ty.ptrInfo(mod);
21192227 if (ptr_info.size == .Slice) {
2120 return mem.eql(u8, field_name, "ptr") or mem.eql(u8, field_name, "len");
2121 } else if (ptr_info.pointee_type.zigTypeTag() == .Array) {
2122 return mem.eql(u8, field_name, "len");
2228 return ip.stringEqlSlice(field_name, "ptr") or ip.stringEqlSlice(field_name, "len");
2229 } else if (ptr_info.pointee_type.zigTypeTag(mod) == .Array) {
2230 return ip.stringEqlSlice(field_name, "len");
21232231 } else return false;
21242232 },
21252233 .Type, .Struct, .Union => return true,
......@@ -2139,7 +2247,7 @@ fn errNote(
21392247) error{OutOfMemory}!void {
21402248 const mod = sema.mod;
21412249 const src_decl = mod.declPtr(block.src_decl);
2142 return mod.errNoteNonLazy(src.toSrcLoc(src_decl), parent, format, args);
2250 return mod.errNoteNonLazy(src.toSrcLoc(src_decl, mod), parent, format, args);
21432251}
21442252
21452253fn addFieldErrNote(
......@@ -2152,19 +2260,19 @@ fn addFieldErrNote(
21522260) !void {
21532261 @setCold(true);
21542262 const mod = sema.mod;
2155 const decl_index = container_ty.getOwnerDecl();
2263 const decl_index = container_ty.getOwnerDecl(mod);
21562264 const decl = mod.declPtr(decl_index);
21572265
21582266 const field_src = blk: {
2159 const tree = decl.getFileScope().getTree(sema.gpa) catch |err| {
2267 const tree = decl.getFileScope(mod).getTree(sema.gpa) catch |err| {
21602268 log.err("unable to load AST to report compile error: {s}", .{@errorName(err)});
2161 break :blk decl.srcLoc();
2269 break :blk decl.srcLoc(mod);
21622270 };
21632271
21642272 const container_node = decl.relativeToNodeIndex(0);
21652273 const node_tags = tree.nodes.items(.tag);
21662274 var buf: [2]std.zig.Ast.Node.Index = undefined;
2167 const container_decl = tree.fullContainerDecl(&buf, container_node) orelse break :blk decl.srcLoc();
2275 const container_decl = tree.fullContainerDecl(&buf, container_node) orelse break :blk decl.srcLoc(mod);
21682276
21692277 var it_index: usize = 0;
21702278 for (container_decl.ast.members) |member_node| {
......@@ -2174,7 +2282,7 @@ fn addFieldErrNote(
21742282 .container_field,
21752283 => {
21762284 if (it_index == field_index) {
2177 break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node));
2285 break :blk decl.nodeOffsetSrcLoc(decl.nodeIndexToRelative(member_node), mod);
21782286 }
21792287 it_index += 1;
21802288 },
......@@ -2195,7 +2303,7 @@ fn errMsg(
21952303) error{OutOfMemory}!*Module.ErrorMsg {
21962304 const mod = sema.mod;
21972305 const src_decl = mod.declPtr(block.src_decl);
2198 return Module.ErrorMsg.create(sema.gpa, src.toSrcLoc(src_decl), format, args);
2306 return Module.ErrorMsg.create(sema.gpa, src.toSrcLoc(src_decl, mod), format, args);
21992307}
22002308
22012309pub fn fail(
......@@ -2212,19 +2320,19 @@ pub fn fail(
22122320fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
22132321 @setCold(true);
22142322 const gpa = sema.gpa;
2323 const mod = sema.mod;
22152324
2216 if (crash_report.is_enabled and sema.mod.comp.debug_compile_errors) {
2325 if (crash_report.is_enabled and mod.comp.debug_compile_errors) {
22172326 if (err_msg.src_loc.lazy == .unneeded) return error.NeededSourceLocation;
22182327 var wip_errors: std.zig.ErrorBundle.Wip = undefined;
22192328 wip_errors.init(gpa) catch unreachable;
2220 Compilation.addModuleErrorMsg(&wip_errors, err_msg.*) catch unreachable;
2329 Compilation.addModuleErrorMsg(mod, &wip_errors, err_msg.*) catch unreachable;
22212330 std.debug.print("compile error during Sema:\n", .{});
22222331 var error_bundle = wip_errors.toOwnedBundle("") catch unreachable;
22232332 error_bundle.renderToStdErr(.{ .ttyconf = .no_color });
22242333 crash_report.compilerPanic("unexpected compile error occurred", null, null);
22252334 }
22262335
2227 const mod = sema.mod;
22282336 ref: {
22292337 errdefer err_msg.destroy(gpa);
22302338 if (err_msg.src_loc.lazy == .unneeded) {
......@@ -2234,9 +2342,9 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
22342342 try mod.failed_files.ensureUnusedCapacity(gpa, 1);
22352343
22362344 const max_references = blk: {
2237 if (sema.mod.comp.reference_trace) |num| break :blk num;
2345 if (mod.comp.reference_trace) |num| break :blk num;
22382346 // Do not add multiple traces without explicit request.
2239 if (sema.mod.failed_decls.count() != 0) break :ref;
2347 if (mod.failed_decls.count() != 0) break :ref;
22402348 break :blk default_reference_trace_len;
22412349 };
22422350
......@@ -2245,7 +2353,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
22452353 defer reference_stack.deinit();
22462354
22472355 // Avoid infinite loops.
2248 var seen = std.AutoHashMap(Module.Decl.Index, void).init(gpa);
2356 var seen = std.AutoHashMap(Decl.Index, void).init(gpa);
22492357 defer seen.deinit();
22502358
22512359 var cur_reference_trace: u32 = 0;
......@@ -2254,13 +2362,16 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
22542362 if (gop.found_existing) break;
22552363 if (cur_reference_trace < max_references) {
22562364 const decl = sema.mod.declPtr(ref.referencer);
2257 try reference_stack.append(.{ .decl = decl.name, .src_loc = ref.src.toSrcLoc(decl) });
2365 try reference_stack.append(.{
2366 .decl = decl.name.toOptional(),
2367 .src_loc = ref.src.toSrcLoc(decl, mod),
2368 });
22582369 }
22592370 referenced_by = ref.referencer;
22602371 }
22612372 if (sema.mod.comp.reference_trace == null and cur_reference_trace > 0) {
22622373 try reference_stack.append(.{
2263 .decl = null,
2374 .decl = .none,
22642375 .src_loc = undefined,
22652376 .hidden = 0,
22662377 });
......@@ -2352,10 +2463,10 @@ fn analyzeAsInt(
23522463 dest_ty: Type,
23532464 reason: []const u8,
23542465) !u64 {
2466 const mod = sema.mod;
23552467 const coerced = try sema.coerce(block, dest_ty, air_ref, src);
23562468 const val = try sema.resolveConstValue(block, src, coerced, reason);
2357 const target = sema.mod.getTarget();
2358 return (try val.getUnsignedIntAdvanced(target, sema)).?;
2469 return (try val.getUnsignedIntAdvanced(mod, sema)).?;
23592470}
23602471
23612472// Returns a compile error if the value has tag `variable`. See `resolveInstValue` for
......@@ -2396,73 +2507,77 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
23962507 const tracy = trace(@src());
23972508 defer tracy.end();
23982509
2510 const mod = sema.mod;
23992511 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
24002512 const src = inst_data.src();
24012513 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
24022514 const pointee_ty = try sema.resolveType(block, src, extra.lhs);
24032515 const ptr = try sema.resolveInst(extra.rhs);
2404 const target = sema.mod.getTarget();
2516 const target = mod.getTarget();
24052517 const addr_space = target_util.defaultAddressSpace(target, .local);
24062518
24072519 if (Air.refToIndex(ptr)) |ptr_inst| {
2408 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
2409 const air_datas = sema.air_instructions.items(.data);
2410 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
2411 switch (ptr_val.tag()) {
2412 .inferred_alloc => {
2413 const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data;
2414 // Add the stored instruction to the set we will use to resolve peer types
2415 // for the inferred allocation.
2416 // This instruction will not make it to codegen; it is only to participate
2417 // in the `stored_inst_list` of the `inferred_alloc`.
2418 var trash_block = block.makeSubBlock();
2419 defer trash_block.instructions.deinit(sema.gpa);
2420 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
2421
2422 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
2423 .pointee_type = pointee_ty,
2424 .@"align" = inferred_alloc.alignment,
2425 .@"addrspace" = addr_space,
2426 });
2427 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
2520 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
2521 .inferred_alloc => {
2522 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
2523 const ia2 = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
2524 // Add the stored instruction to the set we will use to resolve peer types
2525 // for the inferred allocation.
2526 // This instruction will not make it to codegen; it is only to participate
2527 // in the `stored_inst_list` of the `inferred_alloc`.
2528 var trash_block = block.makeSubBlock();
2529 defer trash_block.instructions.deinit(sema.gpa);
2530 const operand = try trash_block.addBitCast(pointee_ty, .void_value);
2531
2532 const ptr_ty = try mod.ptrType(.{
2533 .child = pointee_ty.toIntern(),
2534 .flags = .{
2535 .alignment = ia1.alignment,
2536 .address_space = addr_space,
2537 },
2538 });
2539 const bitcasted_ptr = try block.addBitCast(ptr_ty, ptr);
24282540
2429 try inferred_alloc.prongs.append(sema.arena, .{
2430 .stored_inst = operand,
2431 .placeholder = Air.refToIndex(bitcasted_ptr).?,
2432 });
2541 try ia2.prongs.append(sema.arena, .{
2542 .stored_inst = operand,
2543 .placeholder = Air.refToIndex(bitcasted_ptr).?,
2544 });
24332545
2434 return bitcasted_ptr;
2435 },
2436 .inferred_alloc_comptime => {
2437 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
2438 // There will be only one coerce_result_ptr because we are running at comptime.
2439 // The alloc will turn into a Decl.
2440 var anon_decl = try block.startAnonDecl();
2441 defer anon_decl.deinit();
2442 iac.data.decl_index = try anon_decl.finish(
2443 try pointee_ty.copy(anon_decl.arena()),
2444 Value.undef,
2445 iac.data.alignment,
2446 );
2447 if (iac.data.alignment != 0) {
2448 try sema.resolveTypeLayout(pointee_ty);
2449 }
2450 const ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
2451 .pointee_type = pointee_ty,
2452 .@"align" = iac.data.alignment,
2453 .@"addrspace" = addr_space,
2454 });
2455 try sema.maybeQueueFuncBodyAnalysis(iac.data.decl_index);
2456 return sema.addConstant(
2457 ptr_ty,
2458 try Value.Tag.decl_ref_mut.create(sema.arena, .{
2459 .decl_index = iac.data.decl_index,
2460 .runtime_index = block.runtime_index,
2461 }),
2462 );
2463 },
2464 else => {},
2465 }
2546 return bitcasted_ptr;
2547 },
2548 .inferred_alloc_comptime => {
2549 const alignment = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.alignment;
2550 // There will be only one coerce_result_ptr because we are running at comptime.
2551 // The alloc will turn into a Decl.
2552 var anon_decl = try block.startAnonDecl();
2553 defer anon_decl.deinit();
2554 const decl_index = try anon_decl.finish(
2555 pointee_ty,
2556 (try mod.intern(.{ .undef = pointee_ty.toIntern() })).toValue(),
2557 alignment.toByteUnits(0),
2558 );
2559 sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime.decl_index = decl_index;
2560 if (alignment != .none) {
2561 try sema.resolveTypeLayout(pointee_ty);
2562 }
2563 const ptr_ty = try mod.ptrType(.{
2564 .child = pointee_ty.toIntern(),
2565 .flags = .{
2566 .alignment = alignment,
2567 .address_space = addr_space,
2568 },
2569 });
2570 try sema.maybeQueueFuncBodyAnalysis(decl_index);
2571 try sema.comptime_mutable_decls.append(decl_index);
2572 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
2573 .ty = ptr_ty.toIntern(),
2574 .addr = .{ .mut_decl = .{
2575 .decl = decl_index,
2576 .runtime_index = block.runtime_index,
2577 } },
2578 } })).toValue());
2579 },
2580 else => {},
24662581 }
24672582 }
24682583
......@@ -2487,6 +2602,7 @@ fn coerceResultPtr(
24872602 dummy_operand: Air.Inst.Ref,
24882603 trash_block: *Block,
24892604) CompileError!Air.Inst.Ref {
2605 const mod = sema.mod;
24902606 const target = sema.mod.getTarget();
24912607 const addr_space = target_util.defaultAddressSpace(target, .local);
24922608 const pointee_ty = sema.typeOf(dummy_operand);
......@@ -2530,7 +2646,7 @@ fn coerceResultPtr(
25302646 return sema.addConstant(ptr_ty, ptr_val);
25312647 }
25322648 if (pointee_ty.eql(Type.null, sema.mod)) {
2533 const opt_ty = sema.typeOf(new_ptr).childType();
2649 const opt_ty = sema.typeOf(new_ptr).childType(mod);
25342650 const null_inst = try sema.addConstant(opt_ty, Value.null);
25352651 _ = try block.addBinOp(.store, new_ptr, null_inst);
25362652 return Air.Inst.Ref.void_value;
......@@ -2563,7 +2679,7 @@ fn coerceResultPtr(
25632679 .@"addrspace" = addr_space,
25642680 });
25652681 if (try sema.resolveDefinedValue(block, src, new_ptr)) |ptr_val| {
2566 new_ptr = try sema.addConstant(ptr_operand_ty, ptr_val);
2682 new_ptr = try sema.addConstant(ptr_operand_ty, try mod.getCoerced(ptr_val, ptr_operand_ty));
25672683 } else {
25682684 new_ptr = try sema.bitCast(block, ptr_operand_ty, new_ptr, src, null);
25692685 }
......@@ -2600,8 +2716,10 @@ pub fn analyzeStructDecl(
26002716 sema: *Sema,
26012717 new_decl: *Decl,
26022718 inst: Zir.Inst.Index,
2603 struct_obj: *Module.Struct,
2719 struct_index: Module.Struct.Index,
26042720) SemaError!void {
2721 const mod = sema.mod;
2722 const struct_obj = mod.structPtr(struct_index);
26052723 const extended = sema.code.instructions.items(.data)[inst].extended;
26062724 assert(extended.opcode == .struct_decl);
26072725 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -2630,7 +2748,7 @@ pub fn analyzeStructDecl(
26302748 }
26312749 }
26322750
2633 _ = try sema.mod.scanNamespace(&struct_obj.namespace, extra_index, decls_len, new_decl);
2751 _ = try mod.scanNamespace(struct_obj.namespace, extra_index, decls_len, new_decl);
26342752}
26352753
26362754fn zirStructDecl(
......@@ -2639,28 +2757,35 @@ fn zirStructDecl(
26392757 extended: Zir.Inst.Extended.InstData,
26402758 inst: Zir.Inst.Index,
26412759) CompileError!Air.Inst.Ref {
2760 const mod = sema.mod;
2761 const gpa = sema.gpa;
26422762 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
26432763 const src: LazySrcLoc = if (small.has_src_node) blk: {
26442764 const node_offset = @bitCast(i32, sema.code.extra[extended.operand]);
26452765 break :blk LazySrcLoc.nodeOffset(node_offset);
26462766 } else sema.src;
26472767
2648 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
2649 errdefer new_decl_arena.deinit();
2650 const new_decl_arena_allocator = new_decl_arena.allocator();
2768 // Because these three things each reference each other, `undefined`
2769 // placeholders are used before being set after the struct type gains an
2770 // InternPool index.
26512771
2652 const mod = sema.mod;
2653 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
2654 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
2655 const struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
26562772 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
2657 .ty = Type.type,
2658 .val = struct_val,
2773 .ty = Type.noreturn,
2774 .val = Value.@"unreachable",
26592775 }, small.name_strategy, "struct", inst);
26602776 const new_decl = mod.declPtr(new_decl_index);
26612777 new_decl.owns_tv = true;
26622778 errdefer mod.abortAnonDecl(new_decl_index);
2663 struct_obj.* = .{
2779
2780 const new_namespace_index = try mod.createNamespace(.{
2781 .parent = block.namespace.toOptional(),
2782 .ty = undefined,
2783 .file_scope = block.getFileScope(mod),
2784 });
2785 const new_namespace = mod.namespacePtr(new_namespace_index);
2786 errdefer mod.destroyNamespace(new_namespace_index);
2787
2788 const struct_index = try mod.createStruct(.{
26642789 .owner_decl = new_decl_index,
26652790 .fields = .{},
26662791 .zir_index = inst,
......@@ -2668,18 +2793,25 @@ fn zirStructDecl(
26682793 .status = .none,
26692794 .known_non_opv = undefined,
26702795 .is_tuple = small.is_tuple,
2671 .namespace = .{
2672 .parent = block.namespace,
2673 .ty = struct_ty,
2674 .file_scope = block.getFileScope(),
2675 },
2676 };
2677 std.log.scoped(.module).debug("create struct {*} owned by {*} ({s})", .{
2678 &struct_obj.namespace, new_decl, new_decl.name,
2796 .namespace = new_namespace_index,
26792797 });
2680 try sema.analyzeStructDecl(new_decl, inst, struct_obj);
2681 try new_decl.finalizeNewArena(&new_decl_arena);
2682 return sema.analyzeDeclVal(block, src, new_decl_index);
2798 errdefer mod.destroyStruct(struct_index);
2799
2800 const struct_ty = try mod.intern_pool.get(gpa, .{ .struct_type = .{
2801 .index = struct_index.toOptional(),
2802 .namespace = new_namespace_index.toOptional(),
2803 } });
2804 // TODO: figure out InternPool removals for incremental compilation
2805 //errdefer mod.intern_pool.remove(struct_ty);
2806
2807 new_decl.ty = Type.type;
2808 new_decl.val = struct_ty.toValue();
2809 new_namespace.ty = struct_ty.toType();
2810
2811 try sema.analyzeStructDecl(new_decl, inst, struct_index);
2812 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
2813 try mod.finalizeAnonDecl(new_decl_index);
2814 return decl_val;
26832815}
26842816
26852817fn createAnonymousDeclTypeNamed(
......@@ -2692,6 +2824,7 @@ fn createAnonymousDeclTypeNamed(
26922824 inst: ?Zir.Inst.Index,
26932825) !Decl.Index {
26942826 const mod = sema.mod;
2827 const gpa = sema.gpa;
26952828 const namespace = block.namespace;
26962829 const src_scope = block.wip_capture_scope;
26972830 const src_decl = mod.declPtr(block.src_decl);
......@@ -2707,16 +2840,15 @@ fn createAnonymousDeclTypeNamed(
27072840 // semantically analyzed.
27082841 // This name is also used as the key in the parent namespace so it cannot be
27092842 // renamed.
2710 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{
2711 src_decl.name, anon_prefix, @enumToInt(new_decl_index),
2712 });
2713 errdefer sema.gpa.free(name);
2843
2844 const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
2845 src_decl.name.fmt(&mod.intern_pool), anon_prefix, @enumToInt(new_decl_index),
2846 }) catch unreachable;
27142847 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27152848 return new_decl_index;
27162849 },
27172850 .parent => {
2718 const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
2719 errdefer sema.gpa.free(name);
2851 const name = mod.declPtr(block.src_decl).name;
27202852 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27212853 return new_decl_index;
27222854 },
......@@ -2724,10 +2856,11 @@ fn createAnonymousDeclTypeNamed(
27242856 const fn_info = sema.code.getFnInfo(sema.func.?.zir_body_inst);
27252857 const zir_tags = sema.code.instructions.items(.tag);
27262858
2727 var buf = std.ArrayList(u8).init(sema.gpa);
2859 var buf = std.ArrayList(u8).init(gpa);
27282860 defer buf.deinit();
2729 try buf.appendSlice(mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0));
2730 try buf.appendSlice("(");
2861
2862 const writer = buf.writer();
2863 try writer.print("{}(", .{mod.declPtr(block.src_decl).name.fmt(&mod.intern_pool)});
27312864
27322865 var arg_i: usize = 0;
27332866 for (fn_info.param_body) |zir_inst| switch (zir_tags[zir_inst]) {
......@@ -2741,8 +2874,8 @@ fn createAnonymousDeclTypeNamed(
27412874 const arg_val = sema.resolveConstMaybeUndefVal(block, .unneeded, arg, "") catch
27422875 return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null);
27432876
2744 if (arg_i != 0) try buf.appendSlice(",");
2745 try buf.writer().print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});
2877 if (arg_i != 0) try writer.writeByte(',');
2878 try writer.print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)});
27462879
27472880 arg_i += 1;
27482881 continue;
......@@ -2750,9 +2883,8 @@ fn createAnonymousDeclTypeNamed(
27502883 else => continue,
27512884 };
27522885
2753 try buf.appendSlice(")");
2754 const name = try buf.toOwnedSliceSentinel(0);
2755 errdefer sema.gpa.free(name);
2886 try writer.writeByte(')');
2887 const name = try mod.intern_pool.getOrPutString(gpa, buf.items);
27562888 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27572889 return new_decl_index;
27582890 },
......@@ -2765,10 +2897,9 @@ fn createAnonymousDeclTypeNamed(
27652897 .dbg_var_ptr, .dbg_var_val => {
27662898 if (zir_data[i].str_op.operand != ref) continue;
27672899
2768 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}.{s}", .{
2769 src_decl.name, zir_data[i].str_op.getStr(sema.code),
2900 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}.{s}", .{
2901 src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code),
27702902 });
2771 errdefer sema.gpa.free(name);
27722903
27732904 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name);
27742905 return new_decl_index;
......@@ -2825,53 +2956,28 @@ fn zirEnumDecl(
28252956 break :blk decls_len;
28262957 } else 0;
28272958
2828 var done = false;
2829
2830 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
2831 errdefer if (!done) new_decl_arena.deinit();
2832 const new_decl_arena_allocator = new_decl_arena.allocator();
2959 // Because these three things each reference each other, `undefined`
2960 // placeholders are used before being set after the enum type gains an
2961 // InternPool index.
28332962
2834 const enum_obj = try new_decl_arena_allocator.create(Module.EnumFull);
2835 const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumFull);
2836 enum_ty_payload.* = .{
2837 .base = .{ .tag = if (small.nonexhaustive) .enum_nonexhaustive else .enum_full },
2838 .data = enum_obj,
2839 };
2840 const enum_ty = Type.initPayload(&enum_ty_payload.base);
2841 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
2963 var done = false;
28422964 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
2843 .ty = Type.type,
2844 .val = enum_val,
2965 .ty = Type.noreturn,
2966 .val = Value.@"unreachable",
28452967 }, small.name_strategy, "enum", inst);
28462968 const new_decl = mod.declPtr(new_decl_index);
28472969 new_decl.owns_tv = true;
28482970 errdefer if (!done) mod.abortAnonDecl(new_decl_index);
28492971
2850 enum_obj.* = .{
2851 .owner_decl = new_decl_index,
2852 .tag_ty = Type.null,
2853 .tag_ty_inferred = true,
2854 .fields = .{},
2855 .values = .{},
2856 .namespace = .{
2857 .parent = block.namespace,
2858 .ty = enum_ty,
2859 .file_scope = block.getFileScope(),
2860 },
2861 };
2862 std.log.scoped(.module).debug("create enum {*} owned by {*} ({s})", .{
2863 &enum_obj.namespace, new_decl, new_decl.name,
2972 const new_namespace_index = try mod.createNamespace(.{
2973 .parent = block.namespace.toOptional(),
2974 .ty = undefined,
2975 .file_scope = block.getFileScope(mod),
28642976 });
2977 const new_namespace = mod.namespacePtr(new_namespace_index);
2978 errdefer if (!done) mod.destroyNamespace(new_namespace_index);
28652979
2866 try new_decl.finalizeNewArena(&new_decl_arena);
2867 const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index);
2868 done = true;
2869
2870 var decl_arena: std.heap.ArenaAllocator = undefined;
2871 const decl_arena_allocator = new_decl.value_arena.?.acquire(gpa, &decl_arena);
2872 defer new_decl.value_arena.?.release(&decl_arena);
2873
2874 extra_index = try mod.scanNamespace(&enum_obj.namespace, extra_index, decls_len, new_decl);
2980 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
28752981
28762982 const body = sema.code.extra[extra_index..][0..body_len];
28772983 extra_index += body.len;
......@@ -2880,7 +2986,34 @@ fn zirEnumDecl(
28802986 const body_end = extra_index;
28812987 extra_index += bit_bags_count;
28822988
2883 {
2989 const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| {
2990 if (bag != 0) break true;
2991 } else false;
2992
2993 const incomplete_enum = try mod.intern_pool.getIncompleteEnum(gpa, .{
2994 .decl = new_decl_index,
2995 .namespace = new_namespace_index.toOptional(),
2996 .fields_len = fields_len,
2997 .has_values = any_values,
2998 .tag_mode = if (small.nonexhaustive)
2999 .nonexhaustive
3000 else if (tag_type_ref == .none)
3001 .auto
3002 else
3003 .explicit,
3004 });
3005 // TODO: figure out InternPool removals for incremental compilation
3006 //errdefer if (!done) mod.intern_pool.remove(incomplete_enum.index);
3007
3008 new_decl.ty = Type.type;
3009 new_decl.val = incomplete_enum.index.toValue();
3010 new_namespace.ty = incomplete_enum.index.toType();
3011
3012 const decl_val = try sema.analyzeDeclVal(block, src, new_decl_index);
3013 try mod.finalizeAnonDecl(new_decl_index);
3014 done = true;
3015
3016 const int_tag_ty = ty: {
28843017 // We create a block for the field type instructions because they
28853018 // may need to reference Decls from inside the enum namespace.
28863019 // Within the field type, default value, and alignment expressions, the "owner decl"
......@@ -2896,21 +3029,27 @@ fn zirEnumDecl(
28963029 }
28973030
28983031 const prev_owner_func = sema.owner_func;
3032 const prev_owner_func_index = sema.owner_func_index;
28993033 sema.owner_func = null;
3034 sema.owner_func_index = .none;
29003035 defer sema.owner_func = prev_owner_func;
3036 defer sema.owner_func_index = prev_owner_func_index;
29013037
29023038 const prev_func = sema.func;
3039 const prev_func_index = sema.func_index;
29033040 sema.func = null;
3041 sema.func_index = .none;
29043042 defer sema.func = prev_func;
3043 defer sema.func_index = prev_func_index;
29053044
2906 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
3045 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
29073046 defer wip_captures.deinit();
29083047
29093048 var enum_block: Block = .{
29103049 .parent = null,
29113050 .sema = sema,
29123051 .src_decl = new_decl_index,
2913 .namespace = &enum_obj.namespace,
3052 .namespace = new_namespace_index,
29143053 .wip_capture_scope = wip_captures.scope,
29153054 .instructions = .{},
29163055 .inlining = null,
......@@ -2926,43 +3065,29 @@ fn zirEnumDecl(
29263065
29273066 if (tag_type_ref != .none) {
29283067 const ty = try sema.resolveType(block, tag_ty_src, tag_type_ref);
2929 if (ty.zigTypeTag() != .Int and ty.zigTypeTag() != .ComptimeInt) {
3068 if (ty.zigTypeTag(mod) != .Int and ty.zigTypeTag(mod) != .ComptimeInt) {
29303069 return sema.fail(block, tag_ty_src, "expected integer tag type, found '{}'", .{ty.fmt(sema.mod)});
29313070 }
2932 enum_obj.tag_ty = try ty.copy(decl_arena_allocator);
2933 enum_obj.tag_ty_inferred = false;
3071 incomplete_enum.setTagType(&mod.intern_pool, ty.toIntern());
3072 break :ty ty;
29343073 } else if (fields_len == 0) {
2935 enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, 0);
2936 enum_obj.tag_ty_inferred = true;
3074 break :ty try mod.intType(.unsigned, 0);
29373075 } else {
29383076 const bits = std.math.log2_int_ceil(usize, fields_len);
2939 enum_obj.tag_ty = try Type.Tag.int_unsigned.create(decl_arena_allocator, bits);
2940 enum_obj.tag_ty_inferred = true;
3077 break :ty try mod.intType(.unsigned, bits);
29413078 }
2942 }
3079 };
29433080
2944 if (small.nonexhaustive and enum_obj.tag_ty.zigTypeTag() != .ComptimeInt) {
2945 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == enum_obj.tag_ty.bitSize(sema.mod.getTarget())) {
3081 if (small.nonexhaustive and int_tag_ty.toIntern() != .comptime_int_type) {
3082 if (fields_len > 1 and std.math.log2_int(u64, fields_len) == int_tag_ty.bitSize(mod)) {
29463083 return sema.fail(block, src, "non-exhaustive enum specifies every value", .{});
29473084 }
29483085 }
29493086
2950 try enum_obj.fields.ensureTotalCapacity(decl_arena_allocator, fields_len);
2951 const any_values = for (sema.code.extra[body_end..][0..bit_bags_count]) |bag| {
2952 if (bag != 0) break true;
2953 } else false;
2954 if (any_values) {
2955 try enum_obj.values.ensureTotalCapacityContext(decl_arena_allocator, fields_len, .{
2956 .ty = enum_obj.tag_ty,
2957 .mod = mod,
2958 });
2959 }
2960
29613087 var bit_bag_index: usize = body_end;
29623088 var cur_bit_bag: u32 = undefined;
29633089 var field_i: u32 = 0;
29643090 var last_tag_val: ?Value = null;
2965 var tag_val_buf: Value.Payload.U64 = undefined;
29663091 while (field_i < fields_len) : (field_i += 1) {
29673092 if (field_i % 32 == 0) {
29683093 cur_bit_bag = sema.code.extra[bit_bag_index];
......@@ -2977,15 +3102,12 @@ fn zirEnumDecl(
29773102 // doc comment
29783103 extra_index += 1;
29793104
2980 // This string needs to outlive the ZIR code.
2981 const field_name = try decl_arena_allocator.dupe(u8, field_name_zir);
2982
2983 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);
2984 if (gop_field.found_existing) {
2985 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
2986 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_field.index }).lazy;
3105 const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir);
3106 if (try incomplete_enum.addFieldName(&mod.intern_pool, gpa, field_name)) |other_index| {
3107 const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy;
3108 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy;
29873109 const msg = msg: {
2988 const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name});
3110 const msg = try sema.errMsg(block, field_src, "duplicate enum field '{s}'", .{field_name_zir});
29893111 errdefer msg.destroy(gpa);
29903112 try sema.errNote(block, other_field_src, msg, "other field here", .{});
29913113 break :msg msg;
......@@ -2993,13 +3115,13 @@ fn zirEnumDecl(
29933115 return sema.failWithOwnedErrorMsg(msg);
29943116 }
29953117
2996 if (has_tag_value) {
3118 const tag_overflow = if (has_tag_value) overflow: {
29973119 const tag_val_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
29983120 extra_index += 1;
29993121 const tag_inst = try sema.resolveInst(tag_val_ref);
3000 const tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) {
3122 last_tag_val = sema.resolveConstValue(block, .unneeded, tag_inst, "") catch |err| switch (err) {
30013123 error.NeededSourceLocation => {
3002 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3124 const value_src = mod.fieldSrcLoc(new_decl_index, .{
30033125 .index = field_i,
30043126 .range = .value,
30053127 }).lazy;
......@@ -3008,63 +3130,56 @@ fn zirEnumDecl(
30083130 },
30093131 else => |e| return e,
30103132 };
3011 last_tag_val = tag_val;
3012 const copied_tag_val = try tag_val.copy(decl_arena_allocator);
3013 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
3014 .ty = enum_obj.tag_ty,
3015 .mod = mod,
3016 });
3017 if (gop_val.found_existing) {
3018 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3133 if (!(try sema.intFitsInType(last_tag_val.?, int_tag_ty, null))) break :overflow true;
3134 last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty);
3135 if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| {
3136 const value_src = mod.fieldSrcLoc(new_decl_index, .{
30193137 .index = field_i,
30203138 .range = .value,
30213139 }).lazy;
3022 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
3140 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy;
30233141 const msg = msg: {
3024 const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
3142 const msg = try sema.errMsg(block, value_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)});
30253143 errdefer msg.destroy(gpa);
30263144 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
30273145 break :msg msg;
30283146 };
30293147 return sema.failWithOwnedErrorMsg(msg);
30303148 }
3031 } else if (any_values) {
3032 const tag_val = if (last_tag_val) |val|
3033 try sema.intAdd(val, Value.one, enum_obj.tag_ty)
3149 break :overflow false;
3150 } else if (any_values) overflow: {
3151 var overflow: ?usize = null;
3152 last_tag_val = if (last_tag_val) |val|
3153 try sema.intAdd(val, try mod.intValue(int_tag_ty, 1), int_tag_ty, &overflow)
30343154 else
3035 Value.zero;
3036 last_tag_val = tag_val;
3037 const copied_tag_val = try tag_val.copy(decl_arena_allocator);
3038 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
3039 .ty = enum_obj.tag_ty,
3040 .mod = mod,
3041 });
3042 if (gop_val.found_existing) {
3043 const field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
3044 const other_field_src = enum_obj.fieldSrcLoc(sema.mod, .{ .index = gop_val.index }).lazy;
3155 try mod.intValue(int_tag_ty, 0);
3156 if (overflow != null) break :overflow true;
3157 if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, last_tag_val.?.toIntern())) |other_index| {
3158 const field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = field_i }).lazy;
3159 const other_field_src = mod.fieldSrcLoc(new_decl_index, .{ .index = other_index }).lazy;
30453160 const msg = msg: {
3046 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{tag_val.fmtValue(enum_obj.tag_ty, sema.mod)});
3161 const msg = try sema.errMsg(block, field_src, "enum tag value {} already taken", .{last_tag_val.?.fmtValue(int_tag_ty, sema.mod)});
30473162 errdefer msg.destroy(gpa);
30483163 try sema.errNote(block, other_field_src, msg, "other occurrence here", .{});
30493164 break :msg msg;
30503165 };
30513166 return sema.failWithOwnedErrorMsg(msg);
30523167 }
3053 } else {
3054 tag_val_buf = .{
3055 .base = .{ .tag = .int_u64 },
3056 .data = field_i,
3057 };
3058 last_tag_val = Value.initPayload(&tag_val_buf.base);
3059 }
3168 break :overflow false;
3169 } else overflow: {
3170 last_tag_val = try mod.intValue(Type.comptime_int, field_i);
3171 if (!try sema.intFitsInType(last_tag_val.?, int_tag_ty, null)) break :overflow true;
3172 last_tag_val = try mod.getCoerced(last_tag_val.?, int_tag_ty);
3173 break :overflow false;
3174 };
30603175
3061 if (!(try sema.intFitsInType(last_tag_val.?, enum_obj.tag_ty, null))) {
3062 const value_src = enum_obj.fieldSrcLoc(sema.mod, .{
3176 if (tag_overflow) {
3177 const value_src = mod.fieldSrcLoc(new_decl_index, .{
30633178 .index = field_i,
30643179 .range = if (has_tag_value) .value else .name,
30653180 }).lazy;
30663181 const msg = try sema.errMsg(block, value_src, "enumeration value '{}' too large for type '{}'", .{
3067 last_tag_val.?.fmtValue(enum_obj.tag_ty, mod), enum_obj.tag_ty.fmt(mod),
3182 last_tag_val.?.fmtValue(int_tag_ty, mod), int_tag_ty.fmt(mod),
30683183 });
30693184 return sema.failWithOwnedErrorMsg(msg);
30703185 }
......@@ -3081,6 +3196,8 @@ fn zirUnionDecl(
30813196 const tracy = trace(@src());
30823197 defer tracy.end();
30833198
3199 const mod = sema.mod;
3200 const gpa = sema.gpa;
30843201 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
30853202 var extra_index: usize = extended.operand;
30863203
......@@ -3100,55 +3217,60 @@ fn zirUnionDecl(
31003217 break :blk decls_len;
31013218 } else 0;
31023219
3103 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
3104 errdefer new_decl_arena.deinit();
3105 const new_decl_arena_allocator = new_decl_arena.allocator();
3106
3107 const union_obj = try new_decl_arena_allocator.create(Module.Union);
3108 const type_tag = if (small.has_tag_type or small.auto_enum_tag)
3109 Type.Tag.union_tagged
3110 else if (small.layout != .Auto)
3111 Type.Tag.@"union"
3112 else switch (block.sema.mod.optimizeMode()) {
3113 .Debug, .ReleaseSafe => Type.Tag.union_safety_tagged,
3114 .ReleaseFast, .ReleaseSmall => Type.Tag.@"union",
3115 };
3116 const union_payload = try new_decl_arena_allocator.create(Type.Payload.Union);
3117 union_payload.* = .{
3118 .base = .{ .tag = type_tag },
3119 .data = union_obj,
3120 };
3121 const union_ty = Type.initPayload(&union_payload.base);
3122 const union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty);
3123 const mod = sema.mod;
3220 // Because these three things each reference each other, `undefined`
3221 // placeholders are used before being set after the union type gains an
3222 // InternPool index.
3223
31243224 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3125 .ty = Type.type,
3126 .val = union_val,
3225 .ty = Type.noreturn,
3226 .val = Value.@"unreachable",
31273227 }, small.name_strategy, "union", inst);
31283228 const new_decl = mod.declPtr(new_decl_index);
31293229 new_decl.owns_tv = true;
31303230 errdefer mod.abortAnonDecl(new_decl_index);
3131 union_obj.* = .{
3231
3232 const new_namespace_index = try mod.createNamespace(.{
3233 .parent = block.namespace.toOptional(),
3234 .ty = undefined,
3235 .file_scope = block.getFileScope(mod),
3236 });
3237 const new_namespace = mod.namespacePtr(new_namespace_index);
3238 errdefer mod.destroyNamespace(new_namespace_index);
3239
3240 const union_index = try mod.createUnion(.{
31323241 .owner_decl = new_decl_index,
3133 .tag_ty = Type.initTag(.null),
3242 .tag_ty = Type.null,
31343243 .fields = .{},
31353244 .zir_index = inst,
31363245 .layout = small.layout,
31373246 .status = .none,
3138 .namespace = .{
3139 .parent = block.namespace,
3140 .ty = union_ty,
3141 .file_scope = block.getFileScope(),
3142 },
3143 };
3144 std.log.scoped(.module).debug("create union {*} owned by {*} ({s})", .{
3145 &union_obj.namespace, new_decl, new_decl.name,
3247 .namespace = new_namespace_index,
31463248 });
3147
3148 _ = try mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl);
3149
3150 try new_decl.finalizeNewArena(&new_decl_arena);
3151 return sema.analyzeDeclVal(block, src, new_decl_index);
3249 errdefer mod.destroyUnion(union_index);
3250
3251 const union_ty = try mod.intern_pool.get(gpa, .{ .union_type = .{
3252 .index = union_index,
3253 .runtime_tag = if (small.has_tag_type or small.auto_enum_tag)
3254 .tagged
3255 else if (small.layout != .Auto)
3256 .none
3257 else switch (block.sema.mod.optimizeMode()) {
3258 .Debug, .ReleaseSafe => .safety,
3259 .ReleaseFast, .ReleaseSmall => .none,
3260 },
3261 } });
3262 // TODO: figure out InternPool removals for incremental compilation
3263 //errdefer mod.intern_pool.remove(union_ty);
3264
3265 new_decl.ty = Type.type;
3266 new_decl.val = union_ty.toValue();
3267 new_namespace.ty = union_ty.toType();
3268
3269 _ = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
3270
3271 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3272 try mod.finalizeAnonDecl(new_decl_index);
3273 return decl_val;
31523274}
31533275
31543276fn zirOpaqueDecl(
......@@ -3161,7 +3283,6 @@ fn zirOpaqueDecl(
31613283 defer tracy.end();
31623284
31633285 const mod = sema.mod;
3164 const gpa = sema.gpa;
31653286 const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small);
31663287 var extra_index: usize = extended.operand;
31673288
......@@ -3177,42 +3298,42 @@ fn zirOpaqueDecl(
31773298 break :blk decls_len;
31783299 } else 0;
31793300
3180 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
3181 errdefer new_decl_arena.deinit();
3182 const new_decl_arena_allocator = new_decl_arena.allocator();
3301 // Because these three things each reference each other, `undefined`
3302 // placeholders are used in two places before being set after the opaque
3303 // type gains an InternPool index.
31833304
3184 const opaque_obj = try new_decl_arena_allocator.create(Module.Opaque);
3185 const opaque_ty_payload = try new_decl_arena_allocator.create(Type.Payload.Opaque);
3186 opaque_ty_payload.* = .{
3187 .base = .{ .tag = .@"opaque" },
3188 .data = opaque_obj,
3189 };
3190 const opaque_ty = Type.initPayload(&opaque_ty_payload.base);
3191 const opaque_val = try Value.Tag.ty.create(new_decl_arena_allocator, opaque_ty);
31923305 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3193 .ty = Type.type,
3194 .val = opaque_val,
3306 .ty = Type.noreturn,
3307 .val = Value.@"unreachable",
31953308 }, small.name_strategy, "opaque", inst);
31963309 const new_decl = mod.declPtr(new_decl_index);
31973310 new_decl.owns_tv = true;
31983311 errdefer mod.abortAnonDecl(new_decl_index);
31993312
3200 opaque_obj.* = .{
3201 .owner_decl = new_decl_index,
3202 .namespace = .{
3203 .parent = block.namespace,
3204 .ty = opaque_ty,
3205 .file_scope = block.getFileScope(),
3206 },
3207 };
3208 std.log.scoped(.module).debug("create opaque {*} owned by {*} ({s})", .{
3209 &opaque_obj.namespace, new_decl, new_decl.name,
3313 const new_namespace_index = try mod.createNamespace(.{
3314 .parent = block.namespace.toOptional(),
3315 .ty = undefined,
3316 .file_scope = block.getFileScope(mod),
32103317 });
3318 const new_namespace = mod.namespacePtr(new_namespace_index);
3319 errdefer mod.destroyNamespace(new_namespace_index);
3320
3321 const opaque_ty = try mod.intern(.{ .opaque_type = .{
3322 .decl = new_decl_index,
3323 .namespace = new_namespace_index,
3324 } });
3325 // TODO: figure out InternPool removals for incremental compilation
3326 //errdefer mod.intern_pool.remove(opaque_ty);
32113327
3212 extra_index = try mod.scanNamespace(&opaque_obj.namespace, extra_index, decls_len, new_decl);
3328 new_decl.ty = Type.type;
3329 new_decl.val = opaque_ty.toValue();
3330 new_namespace.ty = opaque_ty.toType();
32133331
3214 try new_decl.finalizeNewArena(&new_decl_arena);
3215 return sema.analyzeDeclVal(block, src, new_decl_index);
3332 extra_index = try mod.scanNamespace(new_namespace_index, extra_index, decls_len, new_decl);
3333
3334 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3335 try mod.finalizeAnonDecl(new_decl_index);
3336 return decl_val;
32163337}
32173338
32183339fn zirErrorSetDecl(
......@@ -3224,48 +3345,39 @@ fn zirErrorSetDecl(
32243345 const tracy = trace(@src());
32253346 defer tracy.end();
32263347
3348 const mod = sema.mod;
32273349 const gpa = sema.gpa;
32283350 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
32293351 const src = inst_data.src();
32303352 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index);
32313353
3232 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
3233 errdefer new_decl_arena.deinit();
3234 const new_decl_arena_allocator = new_decl_arena.allocator();
3235
3236 const error_set = try new_decl_arena_allocator.create(Module.ErrorSet);
3237 const error_set_ty = try Type.Tag.error_set.create(new_decl_arena_allocator, error_set);
3238 const error_set_val = try Value.Tag.ty.create(new_decl_arena_allocator, error_set_ty);
3239 const mod = sema.mod;
3240 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3241 .ty = Type.type,
3242 .val = error_set_val,
3243 }, name_strategy, "error", inst);
3244 const new_decl = mod.declPtr(new_decl_index);
3245 new_decl.owns_tv = true;
3246 errdefer mod.abortAnonDecl(new_decl_index);
3247
3248 var names = Module.ErrorSet.NameMap{};
3249 try names.ensureUnusedCapacity(new_decl_arena_allocator, extra.data.fields_len);
3354 var names: Module.Fn.InferredErrorSet.NameMap = .{};
3355 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len);
32503356
32513357 var extra_index = @intCast(u32, extra.end);
32523358 const extra_index_end = extra_index + (extra.data.fields_len * 2);
32533359 while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
32543360 const str_index = sema.code.extra[extra_index];
3255 const kv = try mod.getErrorValue(sema.code.nullTerminatedString(str_index));
3256 const result = names.getOrPutAssumeCapacity(kv.key);
3361 const name = sema.code.nullTerminatedString(str_index);
3362 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
3363 _ = try mod.getErrorValue(name_ip);
3364 const result = names.getOrPutAssumeCapacity(name_ip);
32573365 assert(!result.found_existing); // verified in AstGen
32583366 }
32593367
3260 // names must be sorted.
3261 Module.ErrorSet.sortNames(&names);
3368 const error_set_ty = try mod.errorSetFromUnsortedNames(names.keys());
32623369
3263 error_set.* = .{
3264 .owner_decl = new_decl_index,
3265 .names = names,
3266 };
3267 try new_decl.finalizeNewArena(&new_decl_arena);
3268 return sema.analyzeDeclVal(block, src, new_decl_index);
3370 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
3371 .ty = Type.type,
3372 .val = error_set_ty.toValue(),
3373 }, name_strategy, "error", inst);
3374 const new_decl = mod.declPtr(new_decl_index);
3375 new_decl.owns_tv = true;
3376 errdefer mod.abortAnonDecl(new_decl_index);
3377
3378 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
3379 try mod.finalizeAnonDecl(new_decl_index);
3380 return decl_val;
32693381}
32703382
32713383fn zirRetPtr(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
......@@ -3319,7 +3431,8 @@ fn ensureResultUsed(
33193431 ty: Type,
33203432 src: LazySrcLoc,
33213433) CompileError!void {
3322 switch (ty.zigTypeTag()) {
3434 const mod = sema.mod;
3435 switch (ty.zigTypeTag(mod)) {
33233436 .Void, .NoReturn => return,
33243437 .ErrorSet, .ErrorUnion => {
33253438 const msg = msg: {
......@@ -3347,11 +3460,12 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
33473460 const tracy = trace(@src());
33483461 defer tracy.end();
33493462
3463 const mod = sema.mod;
33503464 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
33513465 const operand = try sema.resolveInst(inst_data.operand);
33523466 const src = inst_data.src();
33533467 const operand_ty = sema.typeOf(operand);
3354 switch (operand_ty.zigTypeTag()) {
3468 switch (operand_ty.zigTypeTag(mod)) {
33553469 .ErrorSet, .ErrorUnion => {
33563470 const msg = msg: {
33573471 const msg = try sema.errMsg(block, src, "error is discarded", .{});
......@@ -3369,16 +3483,17 @@ fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index
33693483 const tracy = trace(@src());
33703484 defer tracy.end();
33713485
3486 const mod = sema.mod;
33723487 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
33733488 const src = inst_data.src();
33743489 const operand = try sema.resolveInst(inst_data.operand);
33753490 const operand_ty = sema.typeOf(operand);
3376 const err_union_ty = if (operand_ty.zigTypeTag() == .Pointer)
3377 operand_ty.childType()
3491 const err_union_ty = if (operand_ty.zigTypeTag(mod) == .Pointer)
3492 operand_ty.childType(mod)
33783493 else
33793494 operand_ty;
3380 if (err_union_ty.zigTypeTag() != .ErrorUnion) return;
3381 const payload_ty = err_union_ty.errorUnionPayload().zigTypeTag();
3495 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) return;
3496 const payload_ty = err_union_ty.errorUnionPayload(mod).zigTypeTag(mod);
33823497 if (payload_ty != .Void and payload_ty != .NoReturn) {
33833498 const msg = msg: {
33843499 const msg = try sema.errMsg(block, src, "error union payload is ignored", .{});
......@@ -3407,11 +3522,13 @@ fn indexablePtrLen(
34073522 src: LazySrcLoc,
34083523 object: Air.Inst.Ref,
34093524) CompileError!Air.Inst.Ref {
3525 const mod = sema.mod;
34103526 const object_ty = sema.typeOf(object);
3411 const is_pointer_to = object_ty.isSinglePointer();
3412 const indexable_ty = if (is_pointer_to) object_ty.childType() else object_ty;
3527 const is_pointer_to = object_ty.isSinglePointer(mod);
3528 const indexable_ty = if (is_pointer_to) object_ty.childType(mod) else object_ty;
34133529 try checkIndexable(sema, block, src, indexable_ty);
3414 return sema.fieldVal(block, src, object, "len", src);
3530 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len");
3531 return sema.fieldVal(block, src, object, field_name, src);
34153532}
34163533
34173534fn indexablePtrLenOrNone(
......@@ -3420,10 +3537,12 @@ fn indexablePtrLenOrNone(
34203537 src: LazySrcLoc,
34213538 operand: Air.Inst.Ref,
34223539) CompileError!Air.Inst.Ref {
3540 const mod = sema.mod;
34233541 const operand_ty = sema.typeOf(operand);
34243542 try checkMemOperand(sema, block, src, operand_ty);
3425 if (operand_ty.ptrSize() == .Many) return .none;
3426 return sema.fieldVal(block, src, operand, "len", src);
3543 if (operand_ty.ptrSize(mod) == .Many) return .none;
3544 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len");
3545 return sema.fieldVal(block, src, operand, field_name, src);
34273546}
34283547
34293548fn zirAllocExtended(
......@@ -3431,6 +3550,7 @@ fn zirAllocExtended(
34313550 block: *Block,
34323551 extended: Zir.Inst.Extended.InstData,
34333552) CompileError!Air.Inst.Ref {
3553 const gpa = sema.gpa;
34343554 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
34353555 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = extra.data.src_node };
34363556 const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = extra.data.src_node };
......@@ -3451,22 +3571,19 @@ fn zirAllocExtended(
34513571 break :blk alignment;
34523572 } else 0;
34533573
3454 const inferred_alloc_ty = if (small.is_const)
3455 Type.initTag(.inferred_alloc_const)
3456 else
3457 Type.initTag(.inferred_alloc_mut);
3458
34593574 if (block.is_comptime or small.is_comptime) {
34603575 if (small.has_type) {
34613576 return sema.analyzeComptimeAlloc(block, var_ty, alignment);
34623577 } else {
3463 return sema.addConstant(
3464 inferred_alloc_ty,
3465 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
3578 try sema.air_instructions.append(gpa, .{
3579 .tag = .inferred_alloc_comptime,
3580 .data = .{ .inferred_alloc_comptime = .{
34663581 .decl_index = undefined,
3467 .alignment = alignment,
3468 }),
3469 );
3582 .alignment = InternPool.Alignment.fromByteUnits(alignment),
3583 .is_const = small.is_const,
3584 } },
3585 });
3586 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
34703587 }
34713588 }
34723589
......@@ -3484,17 +3601,15 @@ fn zirAllocExtended(
34843601 return block.addTy(.alloc, ptr_type);
34853602 }
34863603
3487 // `Sema.addConstant` does not add the instruction to the block because it is
3488 // not needed in the case of constant values. However here, we plan to "downgrade"
3489 // to a normal instruction when we hit `resolve_inferred_alloc`. So we append
3490 // to the block even though it is currently a `.constant`.
3491 const result = try sema.addConstant(
3492 inferred_alloc_ty,
3493 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = alignment }),
3494 );
3495 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
3496 try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {});
3497 return result;
3604 const result_index = try block.addInstAsIndex(.{
3605 .tag = .inferred_alloc,
3606 .data = .{ .inferred_alloc = .{
3607 .alignment = InternPool.Alignment.fromByteUnits(alignment),
3608 .is_const = small.is_const,
3609 } },
3610 });
3611 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
3612 return Air.indexToRef(result_index);
34983613}
34993614
35003615fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -3508,11 +3623,12 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
35083623}
35093624
35103625fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
3626 const mod = sema.mod;
35113627 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
35123628 const alloc = try sema.resolveInst(inst_data.operand);
35133629 const alloc_ty = sema.typeOf(alloc);
35143630
3515 var ptr_info = alloc_ty.ptrInfo().data;
3631 var ptr_info = alloc_ty.ptrInfo(mod);
35163632 const elem_ty = ptr_info.pointee_type;
35173633
35183634 // Detect if all stores to an `.alloc` were comptime-known.
......@@ -3558,8 +3674,8 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
35583674 var anon_decl = try block.startAnonDecl();
35593675 defer anon_decl.deinit();
35603676 return sema.analyzeDeclRef(try anon_decl.finish(
3561 try elem_ty.copy(anon_decl.arena()),
3562 try store_val.copy(anon_decl.arena()),
3677 elem_ty,
3678 store_val,
35633679 ptr_info.@"align",
35643680 ));
35653681 }
......@@ -3568,15 +3684,16 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
35683684}
35693685
35703686fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref {
3687 const mod = sema.mod;
35713688 const alloc_ty = sema.typeOf(alloc);
35723689
3573 var ptr_info = alloc_ty.ptrInfo().data;
3690 var ptr_info = alloc_ty.ptrInfo(mod);
35743691 ptr_info.mutable = false;
35753692 const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
35763693
35773694 // Detect if a comptime value simply needs to have its type changed.
35783695 if (try sema.resolveMaybeUndefVal(alloc)) |val| {
3579 return sema.addConstant(const_ptr_ty, val);
3696 return sema.addConstant(const_ptr_ty, try mod.getCoerced(val, const_ptr_ty));
35803697 }
35813698
35823699 return block.addBitCast(const_ptr_ty, alloc);
......@@ -3585,18 +3702,22 @@ fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Ai
35853702fn zirAllocInferredComptime(
35863703 sema: *Sema,
35873704 inst: Zir.Inst.Index,
3588 inferred_alloc_ty: Type,
3705 is_const: bool,
35893706) CompileError!Air.Inst.Ref {
3707 const gpa = sema.gpa;
35903708 const src_node = sema.code.instructions.items(.data)[inst].node;
35913709 const src = LazySrcLoc.nodeOffset(src_node);
35923710 sema.src = src;
3593 return sema.addConstant(
3594 inferred_alloc_ty,
3595 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
3711
3712 try sema.air_instructions.append(gpa, .{
3713 .tag = .inferred_alloc_comptime,
3714 .data = .{ .inferred_alloc_comptime = .{
35963715 .decl_index = undefined,
3597 .alignment = 0,
3598 }),
3599 );
3716 .alignment = .none,
3717 .is_const = is_const,
3718 } },
3719 });
3720 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
36003721}
36013722
36023723fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -3642,104 +3763,103 @@ fn zirAllocInferred(
36423763 sema: *Sema,
36433764 block: *Block,
36443765 inst: Zir.Inst.Index,
3645 inferred_alloc_ty: Type,
3766 is_const: bool,
36463767) CompileError!Air.Inst.Ref {
36473768 const tracy = trace(@src());
36483769 defer tracy.end();
36493770
3771 const gpa = sema.gpa;
36503772 const src_node = sema.code.instructions.items(.data)[inst].node;
36513773 const src = LazySrcLoc.nodeOffset(src_node);
36523774 sema.src = src;
36533775
36543776 if (block.is_comptime) {
3655 return sema.addConstant(
3656 inferred_alloc_ty,
3657 try Value.Tag.inferred_alloc_comptime.create(sema.arena, .{
3777 try sema.air_instructions.append(gpa, .{
3778 .tag = .inferred_alloc_comptime,
3779 .data = .{ .inferred_alloc_comptime = .{
36583780 .decl_index = undefined,
3659 .alignment = 0,
3660 }),
3661 );
3781 .alignment = .none,
3782 .is_const = is_const,
3783 } },
3784 });
3785 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
36623786 }
36633787
3664 // `Sema.addConstant` does not add the instruction to the block because it is
3665 // not needed in the case of constant values. However here, we plan to "downgrade"
3666 // to a normal instruction when we hit `resolve_inferred_alloc`. So we append
3667 // to the block even though it is currently a `.constant`.
3668 const result = try sema.addConstant(
3669 inferred_alloc_ty,
3670 try Value.Tag.inferred_alloc.create(sema.arena, .{ .alignment = 0 }),
3671 );
3672 try block.instructions.append(sema.gpa, Air.refToIndex(result).?);
3673 try sema.unresolved_inferred_allocs.putNoClobber(sema.gpa, Air.refToIndex(result).?, {});
3674 return result;
3788 const result_index = try block.addInstAsIndex(.{
3789 .tag = .inferred_alloc,
3790 .data = .{ .inferred_alloc = .{
3791 .alignment = .none,
3792 .is_const = is_const,
3793 } },
3794 });
3795 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{});
3796 return Air.indexToRef(result_index);
36753797}
36763798
36773799fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
36783800 const tracy = trace(@src());
36793801 defer tracy.end();
36803802
3803 const mod = sema.mod;
36813804 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
36823805 const src = inst_data.src();
36833806 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
36843807 const ptr = try sema.resolveInst(inst_data.operand);
36853808 const ptr_inst = Air.refToIndex(ptr).?;
3686 assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
3687 const value_index = sema.air_instructions.items(.data)[ptr_inst].ty_pl.payload;
3688 const ptr_val = sema.air_values.items[value_index];
3689 const var_is_mut = switch (sema.typeOf(ptr).tag()) {
3690 .inferred_alloc_const => false,
3691 .inferred_alloc_mut => true,
3692 else => unreachable,
3693 };
3694 const target = sema.mod.getTarget();
3809 const target = mod.getTarget();
36953810
3696 switch (ptr_val.tag()) {
3811 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
36973812 .inferred_alloc_comptime => {
3698 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
3699 const decl_index = iac.data.decl_index;
3700 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
3701
3702 const decl = sema.mod.declPtr(decl_index);
3703 const final_elem_ty = try decl.ty.copy(sema.arena);
3704 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3705 .pointee_type = final_elem_ty,
3706 .mutable = true,
3707 .@"align" = iac.data.alignment,
3708 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3813 const iac = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
3814 const decl_index = iac.decl_index;
3815 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
3816
3817 const decl = mod.declPtr(decl_index);
3818 if (iac.is_const) try decl.intern(mod);
3819 const final_elem_ty = decl.ty;
3820 const final_ptr_ty = try mod.ptrType(.{
3821 .child = final_elem_ty.toIntern(),
3822 .flags = .{
3823 .is_const = false,
3824 .alignment = iac.alignment,
3825 .address_space = target_util.defaultAddressSpace(target, .local),
3826 },
37093827 });
3710 const final_ptr_ty_inst = try sema.addType(final_ptr_ty);
3711 sema.air_instructions.items(.data)[ptr_inst].ty_pl.ty = final_ptr_ty_inst;
37123828
37133829 try sema.maybeQueueFuncBodyAnalysis(decl_index);
3714 if (var_is_mut) {
3715 sema.air_values.items[value_index] = try Value.Tag.decl_ref_mut.create(sema.arena, .{
3716 .decl_index = decl_index,
3717 .runtime_index = block.runtime_index,
3718 });
3719 } else {
3720 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, decl_index);
3721 }
3830 // Change it to an interned.
3831 sema.air_instructions.set(ptr_inst, .{
3832 .tag = .interned,
3833 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3834 .ty = final_ptr_ty.toIntern(),
3835 .addr = if (!iac.is_const) .{ .mut_decl = .{
3836 .decl = decl_index,
3837 .runtime_index = block.runtime_index,
3838 } } else .{ .decl = decl_index },
3839 } }) },
3840 });
37223841 },
37233842 .inferred_alloc => {
3724 assert(sema.unresolved_inferred_allocs.remove(ptr_inst));
3725 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
3726 const peer_inst_list = inferred_alloc.data.prongs.items(.stored_inst);
3843 const ia1 = sema.air_instructions.items(.data)[ptr_inst].inferred_alloc;
3844 const ia2 = sema.unresolved_inferred_allocs.fetchRemove(ptr_inst).?.value;
3845 const peer_inst_list = ia2.prongs.items(.stored_inst);
37273846 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_inst_list, .none);
37283847
3729 const final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3730 .pointee_type = final_elem_ty,
3731 .mutable = true,
3732 .@"align" = inferred_alloc.data.alignment,
3733 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3848 const final_ptr_ty = try mod.ptrType(.{
3849 .child = final_elem_ty.toIntern(),
3850 .flags = .{
3851 .alignment = ia1.alignment,
3852 .address_space = target_util.defaultAddressSpace(target, .local),
3853 },
37343854 });
37353855
3736 if (var_is_mut) {
3856 if (!ia1.is_const) {
37373857 try sema.validateVarType(block, ty_src, final_elem_ty, false);
37383858 } else ct: {
37393859 // Detect if the value is comptime-known. In such case, the
37403860 // last 3 AIR instructions of the block will look like this:
37413861 //
3742 // %a = constant
3862 // %a = inferred_alloc
37433863 // %b = bitcast(%a)
37443864 // %c = store(%b, %d)
37453865 //
......@@ -3779,43 +3899,46 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
37793899 }
37803900 };
37813901
3782 const const_inst = while (true) {
3902 while (true) {
37833903 if (search_index == 0) break :ct;
37843904 search_index -= 1;
37853905
37863906 const candidate = block.instructions.items[search_index];
3907 if (candidate == ptr_inst) break;
37873908 switch (air_tags[candidate]) {
37883909 .dbg_stmt, .dbg_block_begin, .dbg_block_end => continue,
3789 .constant => break candidate,
37903910 else => break :ct,
37913911 }
3792 };
3912 }
37933913
37943914 const store_op = air_datas[store_inst].bin_op;
37953915 const store_val = (try sema.resolveMaybeUndefVal(store_op.rhs)) orelse break :ct;
37963916 if (store_op.lhs != Air.indexToRef(bitcast_inst)) break :ct;
3797 if (air_datas[bitcast_inst].ty_op.operand != Air.indexToRef(const_inst)) break :ct;
3917 if (air_datas[bitcast_inst].ty_op.operand != ptr) break :ct;
37983918
37993919 const new_decl_index = d: {
38003920 var anon_decl = try block.startAnonDecl();
38013921 defer anon_decl.deinit();
38023922 const new_decl_index = try anon_decl.finish(
3803 try final_elem_ty.copy(anon_decl.arena()),
3804 try store_val.copy(anon_decl.arena()),
3805 inferred_alloc.data.alignment,
3923 final_elem_ty,
3924 store_val,
3925 ia1.alignment.toByteUnits(0),
38063926 );
38073927 break :d new_decl_index;
38083928 };
3809 try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
3929 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
38103930
38113931 // Even though we reuse the constant instruction, we still remove it from the
38123932 // block so that codegen does not see it.
38133933 block.instructions.shrinkRetainingCapacity(search_index);
38143934 try sema.maybeQueueFuncBodyAnalysis(new_decl_index);
3815 sema.air_values.items[value_index] = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
3816 // if bitcast ty ref needs to be made const, make_ptr_const
3817 // ZIR handles it later, so we can just use the ty ref here.
3818 air_datas[ptr_inst].ty_pl.ty = air_datas[bitcast_inst].ty_op.ty;
3935 sema.air_instructions.set(ptr_inst, .{
3936 .tag = .interned,
3937 .data = .{ .interned = try mod.intern(.{ .ptr = .{
3938 .ty = final_ptr_ty.toIntern(),
3939 .addr = .{ .decl = new_decl_index },
3940 } }) },
3941 });
38193942
38203943 // Unless the block is comptime, `alloc_inferred` always produces
38213944 // a runtime constant. The final inferred type needs to be
......@@ -3836,18 +3959,19 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38363959 // Now we need to go back over all the coerce_result_ptr instructions, which
38373960 // previously inserted a bitcast as a placeholder, and do the logic as if
38383961 // the new result ptr type was available.
3839 const placeholders = inferred_alloc.data.prongs.items(.placeholder);
3962 const placeholders = ia2.prongs.items(.placeholder);
38403963 const gpa = sema.gpa;
38413964
38423965 var trash_block = block.makeSubBlock();
38433966 trash_block.is_comptime = false;
38443967 defer trash_block.instructions.deinit(gpa);
38453968
3846 const mut_final_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
3847 .pointee_type = final_elem_ty,
3848 .mutable = true,
3849 .@"align" = inferred_alloc.data.alignment,
3850 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
3969 const mut_final_ptr_ty = try mod.ptrType(.{
3970 .child = final_elem_ty.toIntern(),
3971 .flags = .{
3972 .alignment = ia1.alignment,
3973 .address_space = target_util.defaultAddressSpace(target, .local),
3974 },
38513975 });
38523976 const dummy_ptr = try trash_block.addTy(.alloc, mut_final_ptr_ty);
38533977 const empty_trash_count = trash_block.instructions.items.len;
......@@ -3855,7 +3979,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
38553979 for (peer_inst_list, placeholders) |peer_inst, placeholder_inst| {
38563980 const sub_ptr_ty = sema.typeOf(Air.indexToRef(placeholder_inst));
38573981
3858 if (mut_final_ptr_ty.eql(sub_ptr_ty, sema.mod)) {
3982 if (mut_final_ptr_ty.eql(sub_ptr_ty, mod)) {
38593983 // New result location type is the same as the old one; nothing
38603984 // to do here.
38613985 continue;
......@@ -3920,27 +4044,28 @@ fn zirArrayBasePtr(
39204044 block: *Block,
39214045 inst: Zir.Inst.Index,
39224046) CompileError!Air.Inst.Ref {
4047 const mod = sema.mod;
39234048 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
39244049 const src = inst_data.src();
39254050
39264051 const start_ptr = try sema.resolveInst(inst_data.operand);
39274052 var base_ptr = start_ptr;
3928 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {
4053 while (true) switch (sema.typeOf(base_ptr).childType(mod).zigTypeTag(mod)) {
39294054 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
39304055 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
39314056 else => break,
39324057 };
39334058
3934 const elem_ty = sema.typeOf(base_ptr).childType();
3935 switch (elem_ty.zigTypeTag()) {
4059 const elem_ty = sema.typeOf(base_ptr).childType(mod);
4060 switch (elem_ty.zigTypeTag(mod)) {
39364061 .Array, .Vector => return base_ptr,
3937 .Struct => if (elem_ty.isTuple()) {
4062 .Struct => if (elem_ty.isTuple(mod)) {
39384063 // TODO validate element count
39394064 return base_ptr;
39404065 },
39414066 else => {},
39424067 }
3943 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
4068 return sema.failWithArrayInitNotSupported(block, src, sema.typeOf(start_ptr).childType(mod));
39444069}
39454070
39464071fn zirFieldBasePtr(
......@@ -3948,27 +4073,30 @@ fn zirFieldBasePtr(
39484073 block: *Block,
39494074 inst: Zir.Inst.Index,
39504075) CompileError!Air.Inst.Ref {
4076 const mod = sema.mod;
39514077 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
39524078 const src = inst_data.src();
39534079
39544080 const start_ptr = try sema.resolveInst(inst_data.operand);
39554081 var base_ptr = start_ptr;
3956 while (true) switch (sema.typeOf(base_ptr).childType().zigTypeTag()) {
4082 while (true) switch (sema.typeOf(base_ptr).childType(mod).zigTypeTag(mod)) {
39574083 .ErrorUnion => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true),
39584084 .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true),
39594085 else => break,
39604086 };
39614087
3962 const elem_ty = sema.typeOf(base_ptr).childType();
3963 switch (elem_ty.zigTypeTag()) {
4088 const elem_ty = sema.typeOf(base_ptr).childType(mod);
4089 switch (elem_ty.zigTypeTag(mod)) {
39644090 .Struct, .Union => return base_ptr,
39654091 else => {},
39664092 }
3967 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
4093 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType(mod));
39684094}
39694095
39704096fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
4097 const mod = sema.mod;
39714098 const gpa = sema.gpa;
4099 const ip = &mod.intern_pool;
39724100 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
39734101 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
39744102 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
......@@ -3991,7 +4119,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
39914119 const object_ty = sema.typeOf(object);
39924120 // Each arg could be an indexable, or a range, in which case the length
39934121 // is passed directly as an integer.
3994 const is_int = switch (object_ty.zigTypeTag()) {
4122 const is_int = switch (object_ty.zigTypeTag(mod)) {
39954123 .Int, .ComptimeInt => true,
39964124 else => false,
39974125 };
......@@ -4000,7 +4128,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
40004128 .input_index = i,
40014129 } };
40024130 const arg_len_uncoerced = if (is_int) object else l: {
4003 if (!object_ty.isIndexable()) {
4131 if (!object_ty.isIndexable(mod)) {
40044132 // Instead of using checkIndexable we customize this error.
40054133 const msg = msg: {
40064134 const msg = try sema.errMsg(block, arg_src, "type '{}' is not indexable and not a range", .{object_ty.fmt(sema.mod)});
......@@ -4010,9 +4138,9 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
40104138 };
40114139 return sema.failWithOwnedErrorMsg(msg);
40124140 }
4013 if (!object_ty.indexableHasLen()) continue;
4141 if (!object_ty.indexableHasLen(mod)) continue;
40144142
4015 break :l try sema.fieldVal(block, arg_src, object, "len", arg_src);
4143 break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, "len"), arg_src);
40164144 };
40174145 const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src);
40184146 if (len == .none) {
......@@ -4061,7 +4189,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
40614189 const object_ty = sema.typeOf(object);
40624190 // Each arg could be an indexable, or a range, in which case the length
40634191 // is passed directly as an integer.
4064 switch (object_ty.zigTypeTag()) {
4192 switch (object_ty.zigTypeTag(mod)) {
40654193 .Int, .ComptimeInt => continue,
40664194 else => {},
40674195 }
......@@ -4096,15 +4224,16 @@ fn validateArrayInitTy(
40964224 block: *Block,
40974225 inst: Zir.Inst.Index,
40984226) CompileError!void {
4227 const mod = sema.mod;
40994228 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
41004229 const src = inst_data.src();
41014230 const ty_src: LazySrcLoc = .{ .node_offset_init_ty = inst_data.src_node };
41024231 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data;
41034232 const ty = try sema.resolveType(block, ty_src, extra.ty);
41044233
4105 switch (ty.zigTypeTag()) {
4234 switch (ty.zigTypeTag(mod)) {
41064235 .Array => {
4107 const array_len = ty.arrayLen();
4236 const array_len = ty.arrayLen(mod);
41084237 if (extra.init_count != array_len) {
41094238 return sema.fail(block, src, "expected {d} array elements; found {d}", .{
41104239 array_len, extra.init_count,
......@@ -4113,7 +4242,7 @@ fn validateArrayInitTy(
41134242 return;
41144243 },
41154244 .Vector => {
4116 const array_len = ty.arrayLen();
4245 const array_len = ty.arrayLen(mod);
41174246 if (extra.init_count != array_len) {
41184247 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{
41194248 array_len, extra.init_count,
......@@ -4121,9 +4250,9 @@ fn validateArrayInitTy(
41214250 }
41224251 return;
41234252 },
4124 .Struct => if (ty.isTuple()) {
4253 .Struct => if (ty.isTuple(mod)) {
41254254 _ = try sema.resolveTypeFields(ty);
4126 const array_len = ty.arrayLen();
4255 const array_len = ty.arrayLen(mod);
41274256 if (extra.init_count > array_len) {
41284257 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{
41294258 array_len, extra.init_count,
......@@ -4141,11 +4270,12 @@ fn validateStructInitTy(
41414270 block: *Block,
41424271 inst: Zir.Inst.Index,
41434272) CompileError!void {
4273 const mod = sema.mod;
41444274 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
41454275 const src = inst_data.src();
41464276 const ty = try sema.resolveType(block, src, inst_data.operand);
41474277
4148 switch (ty.zigTypeTag()) {
4278 switch (ty.zigTypeTag(mod)) {
41494279 .Struct, .Union => return,
41504280 else => {},
41514281 }
......@@ -4160,6 +4290,7 @@ fn zirValidateStructInit(
41604290 const tracy = trace(@src());
41614291 defer tracy.end();
41624292
4293 const mod = sema.mod;
41634294 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
41644295 const init_src = validate_inst.src();
41654296 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);
......@@ -4167,8 +4298,8 @@ fn zirValidateStructInit(
41674298 const field_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
41684299 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
41694300 const object_ptr = try sema.resolveInst(field_ptr_extra.lhs);
4170 const agg_ty = sema.typeOf(object_ptr).childType();
4171 switch (agg_ty.zigTypeTag()) {
4301 const agg_ty = sema.typeOf(object_ptr).childType(mod);
4302 switch (agg_ty.zigTypeTag(mod)) {
41724303 .Struct => return sema.validateStructInit(
41734304 block,
41744305 agg_ty,
......@@ -4194,6 +4325,9 @@ fn validateUnionInit(
41944325 instrs: []const Zir.Inst.Index,
41954326 union_ptr: Air.Inst.Ref,
41964327) CompileError!void {
4328 const mod = sema.mod;
4329 const gpa = sema.gpa;
4330
41974331 if (instrs.len != 1) {
41984332 const msg = msg: {
41994333 const msg = try sema.errMsg(
......@@ -4202,7 +4336,7 @@ fn validateUnionInit(
42024336 "cannot initialize multiple union fields at once; unions can only have one active field",
42034337 .{},
42044338 );
4205 errdefer msg.destroy(sema.gpa);
4339 errdefer msg.destroy(gpa);
42064340
42074341 for (instrs[1..]) |inst| {
42084342 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
......@@ -4226,7 +4360,7 @@ fn validateUnionInit(
42264360 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
42274361 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node };
42284362 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
4229 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
4363 const field_name = try mod.intern_pool.getOrPutString(gpa, sema.code.nullTerminatedString(field_ptr_extra.field_name_start));
42304364 // Validate the field access but ignore the index since we want the tag enum field index.
42314365 _ = try sema.unionFieldIndex(block, union_ty, field_name, field_src);
42324366 const air_tags = sema.air_instructions.items(.tag);
......@@ -4291,21 +4425,25 @@ fn validateUnionInit(
42914425 break;
42924426 }
42934427
4294 const tag_ty = union_ty.unionTagTypeHypothetical();
4295 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);
4296 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);
4428 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
4429 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
4430 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
42974431
42984432 if (init_val) |val| {
42994433 // Our task is to delete all the `field_ptr` and `store` instructions, and insert
43004434 // instead a single `store` to the result ptr with a comptime union value.
43014435 block.instructions.shrinkRetainingCapacity(first_block_index);
43024436
4303 var union_val = try Value.Tag.@"union".create(sema.arena, .{
4304 .tag = tag_val,
4305 .val = val,
4306 });
4307 if (make_runtime) union_val = try Value.Tag.runtime_value.create(sema.arena, union_val);
4308 const union_init = try sema.addConstant(union_ty, union_val);
4437 var union_val = try mod.intern(.{ .un = .{
4438 .ty = union_ty.toIntern(),
4439 .tag = tag_val.toIntern(),
4440 .val = val.toIntern(),
4441 } });
4442 if (make_runtime) union_val = try mod.intern(.{ .runtime_value = .{
4443 .ty = union_ty.toIntern(),
4444 .val = union_val,
4445 } });
4446 const union_init = try sema.addConstant(union_ty, union_val.toValue());
43094447 try sema.storePtr2(block, init_src, union_ptr, init_src, union_init, init_src, .store);
43104448 return;
43114449 } else if (try sema.typeRequiresComptime(union_ty)) {
......@@ -4323,10 +4461,12 @@ fn validateStructInit(
43234461 init_src: LazySrcLoc,
43244462 instrs: []const Zir.Inst.Index,
43254463) CompileError!void {
4464 const mod = sema.mod;
43264465 const gpa = sema.gpa;
4466 const ip = &mod.intern_pool;
43274467
43284468 // Maps field index to field_ptr index of where it was already initialized.
4329 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount());
4469 const found_fields = try gpa.alloc(Zir.Inst.Index, struct_ty.structFieldCount(mod));
43304470 defer gpa.free(found_fields);
43314471 @memset(found_fields, 0);
43324472
......@@ -4337,8 +4477,11 @@ fn validateStructInit(
43374477 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_ptr_data.src_node };
43384478 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
43394479 struct_ptr_zir_ref = field_ptr_extra.lhs;
4340 const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
4341 const field_index = if (struct_ty.isTuple())
4480 const field_name = try ip.getOrPutString(
4481 gpa,
4482 sema.code.nullTerminatedString(field_ptr_extra.field_name_start),
4483 );
4484 const field_index = if (struct_ty.isTuple(mod))
43424485 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src)
43434486 else
43444487 try sema.structFieldIndex(block, struct_ty, field_name, field_src);
......@@ -4371,9 +4514,9 @@ fn validateStructInit(
43714514 for (found_fields, 0..) |field_ptr, i| {
43724515 if (field_ptr != 0) continue;
43734516
4374 const default_val = struct_ty.structFieldDefaultValue(i);
4375 if (default_val.tag() == .unreachable_value) {
4376 if (struct_ty.isTuple()) {
4517 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4518 if (default_val.toIntern() == .unreachable_value) {
4519 if (struct_ty.isTuple(mod)) {
43774520 const template = "missing tuple field with index {d}";
43784521 if (root_msg) |msg| {
43794522 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -4382,9 +4525,9 @@ fn validateStructInit(
43824525 }
43834526 continue;
43844527 }
4385 const field_name = struct_ty.structFieldName(i);
4386 const template = "missing struct field: {s}";
4387 const args = .{field_name};
4528 const field_name = struct_ty.structFieldName(i, mod);
4529 const template = "missing struct field: {}";
4530 const args = .{field_name.fmt(ip)};
43884531 if (root_msg) |msg| {
43894532 try sema.errNote(block, init_src, msg, template, args);
43904533 } else {
......@@ -4394,25 +4537,23 @@ fn validateStructInit(
43944537 }
43954538
43964539 const field_src = init_src; // TODO better source location
4397 const default_field_ptr = if (struct_ty.isTuple())
4540 const default_field_ptr = if (struct_ty.isTuple(mod))
43984541 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
43994542 else
44004543 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
4401 const field_ty = sema.typeOf(default_field_ptr).childType();
4544 const field_ty = sema.typeOf(default_field_ptr).childType(mod);
44024545 const init = try sema.addConstant(field_ty, default_val);
44034546 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
44044547 }
44054548
44064549 if (root_msg) |msg| {
4407 if (struct_ty.castTag(.@"struct")) |struct_obj| {
4408 const mod = sema.mod;
4409 const fqn = try struct_obj.data.getFullyQualifiedName(mod);
4410 defer gpa.free(fqn);
4550 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4551 const fqn = try struct_obj.getFullyQualifiedName(mod);
44114552 try mod.errNoteNonLazy(
4412 struct_obj.data.srcLoc(mod),
4553 struct_obj.srcLoc(mod),
44134554 msg,
4414 "struct '{s}' declared here",
4415 .{fqn},
4555 "struct '{}' declared here",
4556 .{fqn.fmt(ip)},
44164557 );
44174558 }
44184559 root_msg = null;
......@@ -4432,14 +4573,14 @@ fn validateStructInit(
44324573
44334574 // We collect the comptime field values in case the struct initialization
44344575 // ends up being comptime-known.
4435 const field_values = try sema.arena.alloc(Value, struct_ty.structFieldCount());
4576 const field_values = try sema.arena.alloc(InternPool.Index, struct_ty.structFieldCount(mod));
44364577
44374578 field: for (found_fields, 0..) |field_ptr, i| {
44384579 if (field_ptr != 0) {
44394580 // Determine whether the value stored to this pointer is comptime-known.
4440 const field_ty = struct_ty.structFieldType(i);
4581 const field_ty = struct_ty.structFieldType(i, mod);
44414582 if (try sema.typeHasOnePossibleValue(field_ty)) |opv| {
4442 field_values[i] = opv;
4583 field_values[i] = opv.toIntern();
44434584 continue;
44444585 }
44454586
......@@ -4504,7 +4645,7 @@ fn validateStructInit(
45044645 first_block_index = @min(first_block_index, block_index);
45054646 }
45064647 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4507 field_values[i] = val;
4648 field_values[i] = val.toIntern();
45084649 } else if (require_comptime) {
45094650 const field_ptr_data = sema.code.instructions.items(.data)[field_ptr].pl_node;
45104651 return sema.failWithNeededComptime(block, field_ptr_data.src(), "initializer of comptime only struct must be comptime-known");
......@@ -4517,9 +4658,9 @@ fn validateStructInit(
45174658 continue :field;
45184659 }
45194660
4520 const default_val = struct_ty.structFieldDefaultValue(i);
4521 if (default_val.tag() == .unreachable_value) {
4522 if (struct_ty.isTuple()) {
4661 const default_val = struct_ty.structFieldDefaultValue(i, mod);
4662 if (default_val.toIntern() == .unreachable_value) {
4663 if (struct_ty.isTuple(mod)) {
45234664 const template = "missing tuple field with index {d}";
45244665 if (root_msg) |msg| {
45254666 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -4528,9 +4669,9 @@ fn validateStructInit(
45284669 }
45294670 continue;
45304671 }
4531 const field_name = struct_ty.structFieldName(i);
4532 const template = "missing struct field: {s}";
4533 const args = .{field_name};
4672 const field_name = struct_ty.structFieldName(i, mod);
4673 const template = "missing struct field: {}";
4674 const args = .{field_name.fmt(ip)};
45344675 if (root_msg) |msg| {
45354676 try sema.errNote(block, init_src, msg, template, args);
45364677 } else {
......@@ -4538,18 +4679,17 @@ fn validateStructInit(
45384679 }
45394680 continue;
45404681 }
4541 field_values[i] = default_val;
4682 field_values[i] = default_val.toIntern();
45424683 }
45434684
45444685 if (root_msg) |msg| {
4545 if (struct_ty.castTag(.@"struct")) |struct_obj| {
4546 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
4547 defer gpa.free(fqn);
4548 try sema.mod.errNoteNonLazy(
4549 struct_obj.data.srcLoc(sema.mod),
4686 if (mod.typeToStruct(struct_ty)) |struct_obj| {
4687 const fqn = try struct_obj.getFullyQualifiedName(mod);
4688 try mod.errNoteNonLazy(
4689 struct_obj.srcLoc(mod),
45504690 msg,
4551 "struct '{s}' declared here",
4552 .{fqn},
4691 "struct '{}' declared here",
4692 .{fqn.fmt(ip)},
45534693 );
45544694 }
45554695 root_msg = null;
......@@ -4561,9 +4701,15 @@ fn validateStructInit(
45614701 // instead a single `store` to the struct_ptr with a comptime struct value.
45624702
45634703 block.instructions.shrinkRetainingCapacity(first_block_index);
4564 var struct_val = try Value.Tag.aggregate.create(sema.arena, field_values);
4565 if (make_runtime) struct_val = try Value.Tag.runtime_value.create(sema.arena, struct_val);
4566 const struct_init = try sema.addConstant(struct_ty, struct_val);
4704 var struct_val = try mod.intern(.{ .aggregate = .{
4705 .ty = struct_ty.toIntern(),
4706 .storage = .{ .elems = field_values },
4707 } });
4708 if (make_runtime) struct_val = try mod.intern(.{ .runtime_value = .{
4709 .ty = struct_ty.toIntern(),
4710 .val = struct_val,
4711 } });
4712 const struct_init = try sema.addConstant(struct_ty, struct_val.toValue());
45674713 try sema.storePtr2(block, init_src, struct_ptr, init_src, struct_init, init_src, .store);
45684714 return;
45694715 }
......@@ -4574,12 +4720,12 @@ fn validateStructInit(
45744720 if (field_ptr != 0) continue;
45754721
45764722 const field_src = init_src; // TODO better source location
4577 const default_field_ptr = if (struct_ty.isTuple())
4723 const default_field_ptr = if (struct_ty.isTuple(mod))
45784724 try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(u32, i), true)
45794725 else
45804726 try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(u32, i), field_src, struct_ty, true);
4581 const field_ty = sema.typeOf(default_field_ptr).childType();
4582 const init = try sema.addConstant(field_ty, field_values[i]);
4727 const field_ty = sema.typeOf(default_field_ptr).childType(mod);
4728 const init = try sema.addConstant(field_ty, field_values[i].toValue());
45834729 try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store);
45844730 }
45854731}
......@@ -4589,6 +4735,7 @@ fn zirValidateArrayInit(
45894735 block: *Block,
45904736 inst: Zir.Inst.Index,
45914737) CompileError!void {
4738 const mod = sema.mod;
45924739 const validate_inst = sema.code.instructions.items(.data)[inst].pl_node;
45934740 const init_src = validate_inst.src();
45944741 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index);
......@@ -4596,18 +4743,18 @@ fn zirValidateArrayInit(
45964743 const first_elem_ptr_data = sema.code.instructions.items(.data)[instrs[0]].pl_node;
45974744 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data;
45984745 const array_ptr = try sema.resolveInst(elem_ptr_extra.ptr);
4599 const array_ty = sema.typeOf(array_ptr).childType();
4600 const array_len = array_ty.arrayLen();
4746 const array_ty = sema.typeOf(array_ptr).childType(mod);
4747 const array_len = array_ty.arrayLen(mod);
46014748
4602 if (instrs.len != array_len) switch (array_ty.zigTypeTag()) {
4749 if (instrs.len != array_len) switch (array_ty.zigTypeTag(mod)) {
46034750 .Struct => {
46044751 var root_msg: ?*Module.ErrorMsg = null;
46054752 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
46064753
46074754 var i = instrs.len;
46084755 while (i < array_len) : (i += 1) {
4609 const default_val = array_ty.structFieldDefaultValue(i);
4610 if (default_val.tag() == .unreachable_value) {
4756 const default_val = array_ty.structFieldDefaultValue(i, mod);
4757 if (default_val.toIntern() == .unreachable_value) {
46114758 const template = "missing tuple field with index {d}";
46124759 if (root_msg) |msg| {
46134760 try sema.errNote(block, init_src, msg, template, .{i});
......@@ -4642,39 +4789,41 @@ fn zirValidateArrayInit(
46424789 // at comptime so we have almost nothing to do here. However, in case of a
46434790 // sentinel-terminated array, the sentinel will not have been populated by
46444791 // any ZIR instructions at comptime; we need to do that here.
4645 if (array_ty.sentinel()) |sentinel_val| {
4792 if (array_ty.sentinel(mod)) |sentinel_val| {
46464793 const array_len_ref = try sema.addIntUnsigned(Type.usize, array_len);
46474794 const sentinel_ptr = try sema.elemPtrArray(block, init_src, init_src, array_ptr, init_src, array_len_ref, true, true);
4648 const sentinel = try sema.addConstant(array_ty.childType(), sentinel_val);
4795 const sentinel = try sema.addConstant(array_ty.childType(mod), sentinel_val);
46494796 try sema.storePtr2(block, init_src, sentinel_ptr, init_src, sentinel, init_src, .store);
46504797 }
46514798 return;
46524799 }
46534800
4801 // If the array has one possible value, the value is always comptime-known.
4802 if (try sema.typeHasOnePossibleValue(array_ty)) |array_opv| {
4803 const array_init = try sema.addConstant(array_ty, array_opv);
4804 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
4805 return;
4806 }
4807
46544808 var array_is_comptime = true;
46554809 var first_block_index = block.instructions.items.len;
46564810 var make_runtime = false;
46574811
46584812 // Collect the comptime element values in case the array literal ends up
46594813 // being comptime-known.
4660 const array_len_s = try sema.usizeCast(block, init_src, array_ty.arrayLenIncludingSentinel());
4661 const element_vals = try sema.arena.alloc(Value, array_len_s);
4662 const opt_opv = try sema.typeHasOnePossibleValue(array_ty);
4814 const element_vals = try sema.arena.alloc(
4815 InternPool.Index,
4816 try sema.usizeCast(block, init_src, array_len),
4817 );
46634818 const air_tags = sema.air_instructions.items(.tag);
46644819 const air_datas = sema.air_instructions.items(.data);
46654820
46664821 outer: for (instrs, 0..) |elem_ptr, i| {
46674822 // Determine whether the value stored to this pointer is comptime-known.
46684823
4669 if (array_ty.isTuple()) {
4670 if (array_ty.structFieldValueComptime(i)) |opv| {
4671 element_vals[i] = opv;
4672 continue;
4673 }
4674 } else {
4675 // Array has one possible value, so value is always comptime-known
4676 if (opt_opv) |opv| {
4677 element_vals[i] = opv;
4824 if (array_ty.isTuple(mod)) {
4825 if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
4826 element_vals[i] = opv.toIntern();
46784827 continue;
46794828 }
46804829 }
......@@ -4735,7 +4884,7 @@ fn zirValidateArrayInit(
47354884 first_block_index = @min(first_block_index, block_index);
47364885 }
47374886 if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(bin_op.rhs, &make_runtime)) |val| {
4738 element_vals[i] = val;
4887 element_vals[i] = val.toIntern();
47394888 } else {
47404889 array_is_comptime = false;
47414890 }
......@@ -4747,50 +4896,55 @@ fn zirValidateArrayInit(
47474896
47484897 if (array_is_comptime) {
47494898 if (try sema.resolveDefinedValue(block, init_src, array_ptr)) |ptr_val| {
4750 if (ptr_val.tag() == .comptime_field_ptr) {
4751 // This store was validated by the individual elem ptrs.
4752 return;
4899 switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {
4900 .ptr => |ptr| switch (ptr.addr) {
4901 .comptime_field => return, // This store was validated by the individual elem ptrs.
4902 else => {},
4903 },
4904 else => {},
47534905 }
47544906 }
47554907
47564908 // Our task is to delete all the `elem_ptr` and `store` instructions, and insert
47574909 // instead a single `store` to the array_ptr with a comptime struct value.
4758 // Also to populate the sentinel value, if any.
4759 if (array_ty.sentinel()) |sentinel_val| {
4760 element_vals[instrs.len] = sentinel_val;
4761 }
4762
47634910 block.instructions.shrinkRetainingCapacity(first_block_index);
47644911
4765 var array_val = try Value.Tag.aggregate.create(sema.arena, element_vals);
4766 if (make_runtime) array_val = try Value.Tag.runtime_value.create(sema.arena, array_val);
4767 const array_init = try sema.addConstant(array_ty, array_val);
4912 var array_val = try mod.intern(.{ .aggregate = .{
4913 .ty = array_ty.toIntern(),
4914 .storage = .{ .elems = element_vals },
4915 } });
4916 if (make_runtime) array_val = try mod.intern(.{ .runtime_value = .{
4917 .ty = array_ty.toIntern(),
4918 .val = array_val,
4919 } });
4920 const array_init = try sema.addConstant(array_ty, array_val.toValue());
47684921 try sema.storePtr2(block, init_src, array_ptr, init_src, array_init, init_src, .store);
47694922 }
47704923}
47714924
47724925fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
4926 const mod = sema.mod;
47734927 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
47744928 const src = inst_data.src();
47754929 const operand = try sema.resolveInst(inst_data.operand);
47764930 const operand_ty = sema.typeOf(operand);
47774931
4778 if (operand_ty.zigTypeTag() != .Pointer) {
4779 return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(sema.mod)});
4780 } else switch (operand_ty.ptrSize()) {
4932 if (operand_ty.zigTypeTag(mod) != .Pointer) {
4933 return sema.fail(block, src, "cannot dereference non-pointer type '{}'", .{operand_ty.fmt(mod)});
4934 } else switch (operand_ty.ptrSize(mod)) {
47814935 .One, .C => {},
4782 .Many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(sema.mod)}),
4783 .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(sema.mod)}),
4936 .Many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{}'", .{operand_ty.fmt(mod)}),
4937 .Slice => return sema.fail(block, src, "index syntax required for slice type '{}'", .{operand_ty.fmt(mod)}),
47844938 }
47854939
4786 if ((try sema.typeHasOnePossibleValue(operand_ty.childType())) != null) {
4940 if ((try sema.typeHasOnePossibleValue(operand_ty.childType(mod))) != null) {
47874941 // No need to validate the actual pointer value, we don't need it!
47884942 return;
47894943 }
47904944
4791 const elem_ty = operand_ty.elemType2();
4945 const elem_ty = operand_ty.elemType2(mod);
47924946 if (try sema.resolveMaybeUndefVal(operand)) |val| {
4793 if (val.isUndef()) {
4947 if (val.isUndef(mod)) {
47944948 return sema.fail(block, src, "cannot dereference undefined value", .{});
47954949 }
47964950 } else if (!(try sema.validateRunTimeType(elem_ty, false))) {
......@@ -4799,12 +4953,12 @@ fn zirValidateDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
47994953 block,
48004954 src,
48014955 "values of type '{}' must be comptime-known, but operand value is runtime-known",
4802 .{elem_ty.fmt(sema.mod)},
4956 .{elem_ty.fmt(mod)},
48034957 );
48044958 errdefer msg.destroy(sema.gpa);
48054959
4806 const src_decl = sema.mod.declPtr(block.src_decl);
4807 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl), elem_ty);
4960 const src_decl = mod.declPtr(block.src_decl);
4961 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl, mod), elem_ty);
48084962 break :msg msg;
48094963 };
48104964 return sema.failWithOwnedErrorMsg(msg);
......@@ -4816,23 +4970,24 @@ fn failWithBadMemberAccess(
48164970 block: *Block,
48174971 agg_ty: Type,
48184972 field_src: LazySrcLoc,
4819 field_name: []const u8,
4973 field_name: InternPool.NullTerminatedString,
48204974) CompileError {
4821 const kw_name = switch (agg_ty.zigTypeTag()) {
4975 const mod = sema.mod;
4976 const kw_name = switch (agg_ty.zigTypeTag(mod)) {
48224977 .Union => "union",
48234978 .Struct => "struct",
48244979 .Opaque => "opaque",
48254980 .Enum => "enum",
48264981 else => unreachable,
48274982 };
4828 if (agg_ty.getOwnerDeclOrNull()) |some| if (sema.mod.declIsRoot(some)) {
4829 return sema.fail(block, field_src, "root struct of file '{}' has no member named '{s}'", .{
4830 agg_ty.fmt(sema.mod), field_name,
4983 if (agg_ty.getOwnerDeclOrNull(mod)) |some| if (mod.declIsRoot(some)) {
4984 return sema.fail(block, field_src, "root struct of file '{}' has no member named '{}'", .{
4985 agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool),
48314986 });
48324987 };
48334988 const msg = msg: {
4834 const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{
4835 kw_name, agg_ty.fmt(sema.mod), field_name,
4989 const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{}'", .{
4990 kw_name, agg_ty.fmt(mod), field_name.fmt(&mod.intern_pool),
48364991 });
48374992 errdefer msg.destroy(sema.gpa);
48384993 try sema.addDeclaredHereNote(msg, agg_ty);
......@@ -4846,22 +5001,22 @@ fn failWithBadStructFieldAccess(
48465001 block: *Block,
48475002 struct_obj: *Module.Struct,
48485003 field_src: LazySrcLoc,
4849 field_name: []const u8,
5004 field_name: InternPool.NullTerminatedString,
48505005) CompileError {
5006 const mod = sema.mod;
48515007 const gpa = sema.gpa;
48525008
4853 const fqn = try struct_obj.getFullyQualifiedName(sema.mod);
4854 defer gpa.free(fqn);
5009 const fqn = try struct_obj.getFullyQualifiedName(mod);
48555010
48565011 const msg = msg: {
48575012 const msg = try sema.errMsg(
48585013 block,
48595014 field_src,
4860 "no field named '{s}' in struct '{s}'",
4861 .{ field_name, fqn },
5015 "no field named '{}' in struct '{}'",
5016 .{ field_name.fmt(&mod.intern_pool), fqn.fmt(&mod.intern_pool) },
48625017 );
48635018 errdefer msg.destroy(gpa);
4864 try sema.mod.errNoteNonLazy(struct_obj.srcLoc(sema.mod), msg, "struct declared here", .{});
5019 try mod.errNoteNonLazy(struct_obj.srcLoc(mod), msg, "struct declared here", .{});
48655020 break :msg msg;
48665021 };
48675022 return sema.failWithOwnedErrorMsg(msg);
......@@ -4872,30 +5027,31 @@ fn failWithBadUnionFieldAccess(
48725027 block: *Block,
48735028 union_obj: *Module.Union,
48745029 field_src: LazySrcLoc,
4875 field_name: []const u8,
5030 field_name: InternPool.NullTerminatedString,
48765031) CompileError {
5032 const mod = sema.mod;
48775033 const gpa = sema.gpa;
48785034
4879 const fqn = try union_obj.getFullyQualifiedName(sema.mod);
4880 defer gpa.free(fqn);
5035 const fqn = try union_obj.getFullyQualifiedName(mod);
48815036
48825037 const msg = msg: {
48835038 const msg = try sema.errMsg(
48845039 block,
48855040 field_src,
4886 "no field named '{s}' in union '{s}'",
4887 .{ field_name, fqn },
5041 "no field named '{}' in union '{}'",
5042 .{ field_name.fmt(&mod.intern_pool), fqn.fmt(&mod.intern_pool) },
48885043 );
48895044 errdefer msg.destroy(gpa);
4890 try sema.mod.errNoteNonLazy(union_obj.srcLoc(sema.mod), msg, "union declared here", .{});
5045 try mod.errNoteNonLazy(union_obj.srcLoc(mod), msg, "union declared here", .{});
48915046 break :msg msg;
48925047 };
48935048 return sema.failWithOwnedErrorMsg(msg);
48945049}
48955050
48965051fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !void {
4897 const src_loc = decl_ty.declSrcLocOrNull(sema.mod) orelse return;
4898 const category = switch (decl_ty.zigTypeTag()) {
5052 const mod = sema.mod;
5053 const src_loc = decl_ty.declSrcLocOrNull(mod) orelse return;
5054 const category = switch (decl_ty.zigTypeTag(mod)) {
48995055 .Union => "union",
49005056 .Struct => "struct",
49015057 .Enum => "enum",
......@@ -4903,7 +5059,7 @@ fn addDeclaredHereNote(sema: *Sema, parent: *Module.ErrorMsg, decl_ty: Type) !vo
49035059 .ErrorSet => "error set",
49045060 else => unreachable,
49055061 };
4906 try sema.mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category});
5062 try mod.errNoteNonLazy(src_loc, parent, "{s} declared here", .{category});
49075063}
49085064
49095065fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
......@@ -4919,17 +5075,14 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
49195075 const src: LazySrcLoc = sema.src;
49205076 blk: {
49215077 const ptr_inst = Air.refToIndex(ptr) orelse break :blk;
4922 if (sema.air_instructions.items(.tag)[ptr_inst] != .constant) break :blk;
4923 const air_datas = sema.air_instructions.items(.data);
4924 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
4925 switch (ptr_val.tag()) {
5078 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
49265079 .inferred_alloc_comptime => {
4927 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
5080 const iac = &sema.air_instructions.items(.data)[ptr_inst].inferred_alloc_comptime;
49285081 return sema.storeToInferredAllocComptime(block, src, operand, iac);
49295082 },
49305083 .inferred_alloc => {
4931 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
4932 return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);
5084 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
5085 return sema.storeToInferredAlloc(block, ptr, operand, ia);
49335086 },
49345087 else => break :blk,
49355088 }
......@@ -4947,18 +5100,16 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
49475100 const ptr = try sema.resolveInst(bin_inst.lhs);
49485101 const operand = try sema.resolveInst(bin_inst.rhs);
49495102 const ptr_inst = Air.refToIndex(ptr).?;
4950 assert(sema.air_instructions.items(.tag)[ptr_inst] == .constant);
49515103 const air_datas = sema.air_instructions.items(.data);
4952 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
49535104
4954 switch (ptr_val.tag()) {
5105 switch (sema.air_instructions.items(.tag)[ptr_inst]) {
49555106 .inferred_alloc_comptime => {
4956 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
5107 const iac = &air_datas[ptr_inst].inferred_alloc_comptime;
49575108 return sema.storeToInferredAllocComptime(block, src, operand, iac);
49585109 },
49595110 .inferred_alloc => {
4960 const inferred_alloc = ptr_val.castTag(.inferred_alloc).?;
4961 return sema.storeToInferredAlloc(block, ptr, operand, inferred_alloc);
5111 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?;
5112 return sema.storeToInferredAlloc(block, ptr, operand, ia);
49625113 },
49635114 else => unreachable,
49645115 }
......@@ -4969,14 +5120,14 @@ fn storeToInferredAlloc(
49695120 block: *Block,
49705121 ptr: Air.Inst.Ref,
49715122 operand: Air.Inst.Ref,
4972 inferred_alloc: *Value.Payload.InferredAlloc,
5123 inferred_alloc: *InferredAlloc,
49735124) CompileError!void {
49745125 // Create a store instruction as a placeholder. This will be replaced by a
49755126 // proper store sequence once we know the stored type.
49765127 const dummy_store = try block.addBinOp(.store, ptr, operand);
49775128 // Add the stored instruction to the set we will use to resolve peer types
49785129 // for the inferred allocation.
4979 try inferred_alloc.data.prongs.append(sema.arena, .{
5130 try inferred_alloc.prongs.append(sema.arena, .{
49805131 .stored_inst = operand,
49815132 .placeholder = Air.refToIndex(dummy_store).?,
49825133 });
......@@ -4987,20 +5138,21 @@ fn storeToInferredAllocComptime(
49875138 block: *Block,
49885139 src: LazySrcLoc,
49895140 operand: Air.Inst.Ref,
4990 iac: *Value.Payload.InferredAllocComptime,
5141 iac: *Air.Inst.Data.InferredAllocComptime,
49915142) CompileError!void {
49925143 const operand_ty = sema.typeOf(operand);
49935144 // There will be only one store_to_inferred_ptr because we are running at comptime.
49945145 // The alloc will turn into a Decl.
49955146 if (try sema.resolveMaybeUndefValAllowVariables(operand)) |operand_val| store: {
4996 if (operand_val.tag() == .variable) break :store;
5147 if (operand_val.getVariable(sema.mod) != null) break :store;
49975148 var anon_decl = try block.startAnonDecl();
49985149 defer anon_decl.deinit();
4999 iac.data.decl_index = try anon_decl.finish(
5000 try operand_ty.copy(anon_decl.arena()),
5001 try operand_val.copy(anon_decl.arena()),
5002 iac.data.alignment,
5150 iac.decl_index = try anon_decl.finish(
5151 operand_ty,
5152 operand_val,
5153 iac.alignment.toByteUnits(0),
50035154 );
5155 try sema.comptime_mutable_decls.append(iac.decl_index);
50045156 return;
50055157 }
50065158
......@@ -5028,6 +5180,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
50285180 const tracy = trace(@src());
50295181 defer tracy.end();
50305182
5183 const mod = sema.mod;
50315184 const zir_tags = sema.code.instructions.items(.tag);
50325185 const zir_datas = sema.code.instructions.items(.data);
50335186 const inst_data = zir_datas[inst].pl_node;
......@@ -5046,9 +5199,9 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
50465199 // %b = store(%a, %c)
50475200 // Where %c is an error union or error set. In such case we need to add
50485201 // to the current function's inferred error set, if any.
5049 if (is_ret and (sema.typeOf(operand).zigTypeTag() == .ErrorUnion or
5050 sema.typeOf(operand).zigTypeTag() == .ErrorSet) and
5051 sema.fn_ret_ty.zigTypeTag() == .ErrorUnion)
5202 if (is_ret and (sema.typeOf(operand).zigTypeTag(mod) == .ErrorUnion or
5203 sema.typeOf(operand).zigTypeTag(mod) == .ErrorSet) and
5204 sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion)
50525205 {
50535206 try sema.addToInferredErrorSet(operand);
50545207 }
......@@ -5072,47 +5225,30 @@ fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
50725225 return sema.addStrLit(block, bytes);
50735226}
50745227
5075fn addStrLit(sema: *Sema, block: *Block, zir_bytes: []const u8) CompileError!Air.Inst.Ref {
5076 // `zir_bytes` references memory inside the ZIR module, which can get deallocated
5077 // after semantic analysis is complete, for example in the case of the initialization
5078 // expression of a variable declaration.
5228fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {
50795229 const mod = sema.mod;
50805230 const gpa = sema.gpa;
5081 const string_bytes = &mod.string_literal_bytes;
5082 const StringLiteralAdapter = Module.StringLiteralAdapter;
5083 const StringLiteralContext = Module.StringLiteralContext;
5084 try string_bytes.ensureUnusedCapacity(gpa, zir_bytes.len);
5085 const gop = try mod.string_literal_table.getOrPutContextAdapted(gpa, zir_bytes, StringLiteralAdapter{
5086 .bytes = string_bytes,
5087 }, StringLiteralContext{
5088 .bytes = string_bytes,
5231 // TODO: write something like getCoercedInts to avoid needing to dupe
5232 const duped_bytes = try sema.arena.dupe(u8, bytes);
5233 const ty = try mod.arrayType(.{
5234 .len = bytes.len,
5235 .child = .u8_type,
5236 .sentinel = .zero_u8,
50895237 });
5238 const val = try mod.intern(.{ .aggregate = .{
5239 .ty = ty.toIntern(),
5240 .storage = .{ .bytes = duped_bytes },
5241 } });
5242 const gop = try mod.memoized_decls.getOrPut(gpa, val);
50905243 if (!gop.found_existing) {
5091 gop.key_ptr.* = .{
5092 .index = @intCast(u32, string_bytes.items.len),
5093 .len = @intCast(u32, zir_bytes.len),
5094 };
5095 string_bytes.appendSliceAssumeCapacity(zir_bytes);
5096 gop.value_ptr.* = .none;
5244 const new_decl_index = try mod.createAnonymousDecl(block, .{
5245 .ty = ty,
5246 .val = val.toValue(),
5247 });
5248 gop.value_ptr.* = new_decl_index;
5249 try mod.finalizeAnonDecl(new_decl_index);
50975250 }
5098 const decl_index = gop.value_ptr.unwrap() orelse di: {
5099 var anon_decl = try block.startAnonDecl();
5100 defer anon_decl.deinit();
5101
5102 const decl_index = try anon_decl.finish(
5103 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), gop.key_ptr.len),
5104 try Value.Tag.str_lit.create(anon_decl.arena(), gop.key_ptr.*),
5105 0, // default alignment
5106 );
5107
5108 // Needed so that `Decl.clearValues` will additionally set the corresponding
5109 // string literal table value back to `Decl.OptionalIndex.none`.
5110 mod.declPtr(decl_index).owns_tv = true;
5111
5112 gop.value_ptr.* = decl_index.toOptional();
5113 break :di decl_index;
5114 };
5115 return sema.analyzeDeclRef(decl_index);
5251 return sema.analyzeDeclRef(gop.value_ptr.*);
51165252}
51175253
51185254fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -5121,7 +5257,7 @@ fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
51215257 defer tracy.end();
51225258
51235259 const int = sema.code.instructions.items(.data)[inst].int;
5124 return sema.addIntUnsigned(Type.initTag(.comptime_int), int);
5260 return sema.addIntUnsigned(Type.comptime_int, int);
51255261}
51265262
51275263fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -5129,38 +5265,43 @@ fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
51295265 const tracy = trace(@src());
51305266 defer tracy.end();
51315267
5132 const arena = sema.arena;
5268 const mod = sema.mod;
51335269 const int = sema.code.instructions.items(.data)[inst].str;
51345270 const byte_count = int.len * @sizeOf(std.math.big.Limb);
51355271 const limb_bytes = sema.code.string_bytes[int.start..][0..byte_count];
5136 const limbs = try arena.alloc(std.math.big.Limb, int.len);
5272
5273 // TODO: this allocation and copy is only needed because the limbs may be unaligned.
5274 // If ZIR is adjusted so that big int limbs are guaranteed to be aligned, these
5275 // two lines can be removed.
5276 const limbs = try sema.arena.alloc(std.math.big.Limb, int.len);
51375277 @memcpy(mem.sliceAsBytes(limbs), limb_bytes);
51385278
51395279 return sema.addConstant(
5140 Type.initTag(.comptime_int),
5141 try Value.Tag.int_big_positive.create(arena, limbs),
5280 Type.comptime_int,
5281 try mod.intValue_big(Type.comptime_int, .{
5282 .limbs = limbs,
5283 .positive = true,
5284 }),
51425285 );
51435286}
51445287
51455288fn zirFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
51465289 _ = block;
5147 const arena = sema.arena;
51485290 const number = sema.code.instructions.items(.data)[inst].float;
51495291 return sema.addConstant(
5150 Type.initTag(.comptime_float),
5151 try Value.Tag.float_64.create(arena, number),
5292 Type.comptime_float,
5293 try sema.mod.floatValue(Type.comptime_float, number),
51525294 );
51535295}
51545296
51555297fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
51565298 _ = block;
5157 const arena = sema.arena;
51585299 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
51595300 const extra = sema.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data;
51605301 const number = extra.get();
51615302 return sema.addConstant(
5162 Type.initTag(.comptime_float),
5163 try Value.Tag.float_128.create(arena, number),
5303 Type.comptime_float,
5304 try sema.mod.floatValue(Type.comptime_float, number),
51645305 );
51655306}
51665307
......@@ -5179,7 +5320,9 @@ fn zirCompileLog(
51795320 sema: *Sema,
51805321 extended: Zir.Inst.Extended.InstData,
51815322) CompileError!Air.Inst.Ref {
5182 var managed = sema.mod.compile_log_text.toManaged(sema.gpa);
5323 const mod = sema.mod;
5324
5325 var managed = mod.compile_log_text.toManaged(sema.gpa);
51835326 defer sema.mod.compile_log_text = managed.moveToUnmanaged();
51845327 const writer = managed.writer();
51855328
......@@ -5192,19 +5335,18 @@ fn zirCompileLog(
51925335
51935336 const arg = try sema.resolveInst(arg_ref);
51945337 const arg_ty = sema.typeOf(arg);
5195 if (try sema.resolveMaybeUndefVal(arg)) |val| {
5196 try sema.resolveLazyValue(val);
5338 if (try sema.resolveMaybeUndefLazyVal(arg)) |val| {
51975339 try writer.print("@as({}, {})", .{
5198 arg_ty.fmt(sema.mod), val.fmtValue(arg_ty, sema.mod),
5340 arg_ty.fmt(mod), val.fmtValue(arg_ty, mod),
51995341 });
52005342 } else {
5201 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(sema.mod)});
5343 try writer.print("@as({}, [runtime value])", .{arg_ty.fmt(mod)});
52025344 }
52035345 }
52045346 try writer.print("\n", .{});
52055347
52065348 const decl_index = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;
5207 const gop = try sema.mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
5349 const gop = try mod.compile_log_decls.getOrPut(sema.gpa, decl_index);
52085350 if (!gop.found_existing) {
52095351 gop.value_ptr.* = src_node;
52105352 }
......@@ -5235,6 +5377,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
52355377 const tracy = trace(@src());
52365378 defer tracy.end();
52375379
5380 const mod = sema.mod;
52385381 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
52395382 const src = inst_data.src();
52405383 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index);
......@@ -5284,7 +5427,7 @@ fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError
52845427 try sema.analyzeBody(&loop_block, body);
52855428
52865429 const loop_block_len = loop_block.instructions.items.len;
5287 if (loop_block_len > 0 and sema.typeOf(Air.indexToRef(loop_block.instructions.items[loop_block_len - 1])).isNoReturn()) {
5430 if (loop_block_len > 0 and sema.typeOf(Air.indexToRef(loop_block.instructions.items[loop_block_len - 1])).isNoReturn(mod)) {
52885431 // If the loop ended with a noreturn terminator, then there is no way for it to loop,
52895432 // so we can just use the block instead.
52905433 try child_block.instructions.appendSlice(gpa, loop_block.instructions.items);
......@@ -5311,7 +5454,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
53115454
53125455 // we check this here to avoid undefined symbols
53135456 if (!@import("build_options").have_llvm)
5314 return sema.fail(parent_block, src, "cannot do C import on Zig compiler not built with LLVM-extension", .{});
5457 return sema.fail(parent_block, src, "C import unavailable; Zig compiler built without LLVM extensions", .{});
53155458
53165459 var c_import_buf = std.ArrayList(u8).init(sema.gpa);
53175460 defer c_import_buf.deinit();
......@@ -5354,7 +5497,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
53545497 if (!mod.comp.bin_file.options.link_libc)
53555498 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});
53565499
5357 const gop = try sema.mod.cimport_errors.getOrPut(sema.gpa, sema.owner_decl_index);
5500 const gop = try mod.cimport_errors.getOrPut(sema.gpa, sema.owner_decl_index);
53585501 if (!gop.found_existing) {
53595502 var errs = try std.ArrayListUnmanaged(Module.CImportError).initCapacity(sema.gpa, c_import_res.errors.len);
53605503 errdefer {
......@@ -5537,7 +5680,7 @@ fn analyzeBlockBody(
55375680
55385681 // Blocks must terminate with noreturn instruction.
55395682 assert(child_block.instructions.items.len != 0);
5540 assert(sema.typeOf(Air.indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1])).isNoReturn());
5683 assert(sema.typeOf(Air.indexToRef(child_block.instructions.items[child_block.instructions.items.len - 1])).isNoReturn(mod));
55415684
55425685 if (merges.results.items.len == 0) {
55435686 // No need for a block instruction. We can put the new instructions
......@@ -5578,7 +5721,7 @@ fn analyzeBlockBody(
55785721 try sema.errNote(child_block, runtime_src, msg, "runtime control flow here", .{});
55795722
55805723 const child_src_decl = mod.declPtr(child_block.src_decl);
5581 try sema.explainWhyTypeIsComptime(msg, type_src.toSrcLoc(child_src_decl), resolved_ty);
5724 try sema.explainWhyTypeIsComptime(msg, type_src.toSrcLoc(child_src_decl, mod), resolved_ty);
55825725
55835726 break :msg msg;
55845727 };
......@@ -5649,15 +5792,16 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
56495792 const tracy = trace(@src());
56505793 defer tracy.end();
56515794
5795 const mod = sema.mod;
56525796 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
56535797 const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data;
56545798 const src = inst_data.src();
56555799 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
56565800 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
5657 const decl_name = sema.code.nullTerminatedString(extra.decl_name);
5801 const decl_name = try mod.intern_pool.getOrPutString(mod.gpa, sema.code.nullTerminatedString(extra.decl_name));
56585802 const decl_index = if (extra.namespace != .none) index_blk: {
56595803 const container_ty = try sema.resolveType(block, operand_src, extra.namespace);
5660 const container_namespace = container_ty.getNamespace().?;
5804 const container_namespace = container_ty.getNamespaceIndex(mod).unwrap().?;
56615805
56625806 const maybe_index = try sema.lookupInNamespace(block, operand_src, container_namespace, decl_name, false);
56635807 break :index_blk maybe_index orelse
......@@ -5671,10 +5815,10 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
56715815 else => |e| return e,
56725816 };
56735817 {
5674 try sema.mod.ensureDeclAnalyzed(decl_index);
5675 const exported_decl = sema.mod.declPtr(decl_index);
5676 if (exported_decl.val.castTag(.function)) |some| {
5677 return sema.analyzeExport(block, src, options, some.data.owner_decl);
5818 try mod.ensureDeclAnalyzed(decl_index);
5819 const exported_decl = mod.declPtr(decl_index);
5820 if (exported_decl.val.getFunction(mod)) |function| {
5821 return sema.analyzeExport(block, src, options, function.owner_decl);
56785822 }
56795823 }
56805824 try sema.analyzeExport(block, src, options, decl_index);
......@@ -5697,17 +5841,14 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
56975841 },
56985842 else => |e| return e,
56995843 };
5700 const decl_index = switch (operand.val.tag()) {
5701 .function => operand.val.castTag(.function).?.data.owner_decl,
5702 else => blk: {
5703 var anon_decl = try block.startAnonDecl();
5704 defer anon_decl.deinit();
5705 break :blk try anon_decl.finish(
5706 try operand.ty.copy(anon_decl.arena()),
5707 try operand.val.copy(anon_decl.arena()),
5708 0,
5709 );
5710 },
5844 const decl_index = if (operand.val.getFunction(sema.mod)) |function| function.owner_decl else blk: {
5845 var anon_decl = try block.startAnonDecl();
5846 defer anon_decl.deinit();
5847 break :blk try anon_decl.finish(
5848 operand.ty,
5849 operand.val,
5850 0,
5851 );
57115852 };
57125853 try sema.analyzeExport(block, src, options, decl_index);
57135854}
......@@ -5716,13 +5857,13 @@ pub fn analyzeExport(
57165857 sema: *Sema,
57175858 block: *Block,
57185859 src: LazySrcLoc,
5719 borrowed_options: std.builtin.ExportOptions,
5860 options: Module.Export.Options,
57205861 exported_decl_index: Decl.Index,
57215862) !void {
57225863 const Export = Module.Export;
57235864 const mod = sema.mod;
57245865
5725 if (borrowed_options.linkage == .Internal) {
5866 if (options.linkage == .Internal) {
57265867 return;
57275868 }
57285869
......@@ -5731,11 +5872,11 @@ pub fn analyzeExport(
57315872
57325873 if (!try sema.validateExternType(exported_decl.ty, .other)) {
57335874 const msg = msg: {
5734 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(sema.mod)});
5875 const msg = try sema.errMsg(block, src, "unable to export type '{}'", .{exported_decl.ty.fmt(mod)});
57355876 errdefer msg.destroy(sema.gpa);
57365877
5737 const src_decl = sema.mod.declPtr(block.src_decl);
5738 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), exported_decl.ty, .other);
5878 const src_decl = mod.declPtr(block.src_decl);
5879 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), exported_decl.ty, .other);
57395880
57405881 try sema.addDeclaredHereNote(msg, exported_decl.ty);
57415882 break :msg msg;
......@@ -5744,15 +5885,15 @@ pub fn analyzeExport(
57445885 }
57455886
57465887 // TODO: some backends might support re-exporting extern decls
5747 if (exported_decl.isExtern()) {
5888 if (exported_decl.isExtern(mod)) {
57485889 return sema.fail(block, src, "export target cannot be extern", .{});
57495890 }
57505891
57515892 // This decl is alive no matter what, since it's being exported
5752 mod.markDeclAlive(exported_decl);
5893 try mod.markDeclAlive(exported_decl);
57535894 try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
57545895
5755 const gpa = mod.gpa;
5896 const gpa = sema.gpa;
57565897
57575898 try mod.decl_exports.ensureUnusedCapacity(gpa, 1);
57585899 try mod.export_owners.ensureUnusedCapacity(gpa, 1);
......@@ -5760,19 +5901,8 @@ pub fn analyzeExport(
57605901 const new_export = try gpa.create(Export);
57615902 errdefer gpa.destroy(new_export);
57625903
5763 const symbol_name = try gpa.dupe(u8, borrowed_options.name);
5764 errdefer gpa.free(symbol_name);
5765
5766 const section: ?[]const u8 = if (borrowed_options.section) |s| try gpa.dupe(u8, s) else null;
5767 errdefer if (section) |s| gpa.free(s);
5768
57695904 new_export.* = .{
5770 .options = .{
5771 .name = symbol_name,
5772 .linkage = borrowed_options.linkage,
5773 .section = section,
5774 .visibility = borrowed_options.visibility,
5775 },
5905 .opts = options,
57765906 .src = src,
57775907 .owner_decl = sema.owner_decl_index,
57785908 .src_decl = block.src_decl,
......@@ -5798,6 +5928,7 @@ pub fn analyzeExport(
57985928}
57995929
58005930fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void {
5931 const mod = sema.mod;
58015932 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
58025933 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
58035934 const src = LazySrcLoc.nodeOffset(extra.node);
......@@ -5807,11 +5938,12 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
58075938 alignment,
58085939 });
58095940 }
5810 const func = sema.func orelse
5941 const func_index = sema.func_index.unwrap() orelse
58115942 return sema.fail(block, src, "@setAlignStack outside function body", .{});
5943 const func = mod.funcPtr(func_index);
58125944
5813 const fn_owner_decl = sema.mod.declPtr(func.owner_decl);
5814 switch (fn_owner_decl.ty.fnCallingConvention()) {
5945 const fn_owner_decl = mod.declPtr(func.owner_decl);
5946 switch (fn_owner_decl.ty.fnCallingConvention(mod)) {
58155947 .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}),
58165948 .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}),
58175949 else => if (block.inlining != null) {
......@@ -5819,7 +5951,7 @@ fn zirSetAlignStack(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
58195951 },
58205952 }
58215953
5822 const gop = try sema.mod.align_stack_fns.getOrPut(sema.mod.gpa, func);
5954 const gop = try mod.align_stack_fns.getOrPut(sema.gpa, func_index);
58235955 if (gop.found_existing) {
58245956 const msg = msg: {
58255957 const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{});
......@@ -5971,10 +6103,11 @@ fn addDbgVar(
59716103 air_tag: Air.Inst.Tag,
59726104 name: []const u8,
59736105) CompileError!void {
6106 const mod = sema.mod;
59746107 const operand_ty = sema.typeOf(operand);
59756108 switch (air_tag) {
59766109 .dbg_var_ptr => {
5977 if (!(try sema.typeHasRuntimeBits(operand_ty.childType()))) return;
6110 if (!(try sema.typeHasRuntimeBits(operand_ty.childType(mod)))) return;
59786111 },
59796112 .dbg_var_val => {
59806113 if (!(try sema.typeHasRuntimeBits(operand_ty))) return;
......@@ -6003,29 +6136,32 @@ fn addDbgVar(
60036136}
60046137
60056138fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6139 const mod = sema.mod;
60066140 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
60076141 const src = inst_data.src();
6008 const decl_name = inst_data.get(sema.code);
6142 const decl_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
60096143 const decl_index = try sema.lookupIdentifier(block, src, decl_name);
60106144 try sema.addReferencedBy(block, src, decl_index);
60116145 return sema.analyzeDeclRef(decl_index);
60126146}
60136147
60146148fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6149 const mod = sema.mod;
60156150 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
60166151 const src = inst_data.src();
6017 const decl_name = inst_data.get(sema.code);
6152 const decl_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
60186153 const decl = try sema.lookupIdentifier(block, src, decl_name);
60196154 return sema.analyzeDeclVal(block, src, decl);
60206155}
60216156
6022fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: []const u8) !Decl.Index {
6157fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: InternPool.NullTerminatedString) !Decl.Index {
6158 const mod = sema.mod;
60236159 var namespace = block.namespace;
60246160 while (true) {
60256161 if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl_index| {
60266162 return decl_index;
60276163 }
6028 namespace = namespace.parent orelse break;
6164 namespace = mod.namespacePtr(namespace).parent.unwrap() orelse break;
60296165 }
60306166 unreachable; // AstGen detects use of undeclared identifier errors.
60316167}
......@@ -6036,21 +6172,22 @@ fn lookupInNamespace(
60366172 sema: *Sema,
60376173 block: *Block,
60386174 src: LazySrcLoc,
6039 namespace: *Namespace,
6040 ident_name: []const u8,
6175 namespace_index: Namespace.Index,
6176 ident_name: InternPool.NullTerminatedString,
60416177 observe_usingnamespace: bool,
60426178) CompileError!?Decl.Index {
60436179 const mod = sema.mod;
60446180
6045 const namespace_decl_index = namespace.getDeclIndex();
6046 const namespace_decl = sema.mod.declPtr(namespace_decl_index);
6181 const namespace = mod.namespacePtr(namespace_index);
6182 const namespace_decl_index = namespace.getDeclIndex(mod);
6183 const namespace_decl = mod.declPtr(namespace_decl_index);
60476184 if (namespace_decl.analysis == .file_failure) {
60486185 try mod.declareDeclDependency(sema.owner_decl_index, namespace_decl_index);
60496186 return error.AnalysisFail;
60506187 }
60516188
60526189 if (observe_usingnamespace and namespace.usingnamespace_set.count() != 0) {
6053 const src_file = block.namespace.file_scope;
6190 const src_file = mod.namespacePtr(block.namespace).file_scope;
60546191
60556192 const gpa = sema.gpa;
60566193 var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, bool) = .{};
......@@ -6069,7 +6206,7 @@ fn lookupInNamespace(
60696206 // Skip decls which are not marked pub, which are in a different
60706207 // file than the `a.b`/`@hasDecl` syntax.
60716208 const decl = mod.declPtr(decl_index);
6072 if (decl.is_pub or (src_file == decl.getFileScope() and checked_namespaces.values()[check_i])) {
6209 if (decl.is_pub or (src_file == decl.getFileScope(mod) and checked_namespaces.values()[check_i])) {
60736210 try candidates.append(gpa, decl_index);
60746211 }
60756212 }
......@@ -6080,15 +6217,15 @@ fn lookupInNamespace(
60806217 if (sub_usingnamespace_decl_index == sema.owner_decl_index) continue;
60816218 const sub_usingnamespace_decl = mod.declPtr(sub_usingnamespace_decl_index);
60826219 const sub_is_pub = entry.value_ptr.*;
6083 if (!sub_is_pub and src_file != sub_usingnamespace_decl.getFileScope()) {
6220 if (!sub_is_pub and src_file != sub_usingnamespace_decl.getFileScope(mod)) {
60846221 // Skip usingnamespace decls which are not marked pub, which are in
60856222 // a different file than the `a.b`/`@hasDecl` syntax.
60866223 continue;
60876224 }
60886225 try sema.ensureDeclAnalyzed(sub_usingnamespace_decl_index);
6089 const ns_ty = sub_usingnamespace_decl.val.castTag(.ty).?.data;
6090 const sub_ns = ns_ty.getNamespace().?;
6091 try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope());
6226 const ns_ty = sub_usingnamespace_decl.val.toType();
6227 const sub_ns = ns_ty.getNamespace(mod).?;
6228 try checked_namespaces.put(gpa, sub_ns, src_file == sub_usingnamespace_decl.getFileScope(mod));
60926229 }
60936230 }
60946231
......@@ -6116,7 +6253,7 @@ fn lookupInNamespace(
61166253 errdefer msg.destroy(gpa);
61176254 for (candidates.items) |candidate_index| {
61186255 const candidate = mod.declPtr(candidate_index);
6119 const src_loc = candidate.srcLoc();
6256 const src_loc = candidate.srcLoc(mod);
61206257 try mod.errNoteNonLazy(src_loc, msg, "declared here", .{});
61216258 }
61226259 break :msg msg;
......@@ -6129,9 +6266,6 @@ fn lookupInNamespace(
61296266 return decl_index;
61306267 }
61316268
6132 log.debug("{*} ({s}) depends on non-existence of '{s}' in {*} ({s})", .{
6133 sema.owner_decl, sema.owner_decl.name, ident_name, namespace_decl, namespace_decl.name,
6134 });
61356269 // TODO This dependency is too strong. Really, it should only be a dependency
61366270 // on the non-existence of `ident_name` in the namespace. We can lessen the number of
61376271 // outdated declarations by making this dependency more sophisticated.
......@@ -6140,22 +6274,28 @@ fn lookupInNamespace(
61406274}
61416275
61426276fn funcDeclSrc(sema: *Sema, func_inst: Air.Inst.Ref) !?*Decl {
6277 const mod = sema.mod;
61436278 const func_val = (try sema.resolveMaybeUndefVal(func_inst)) orelse return null;
6144 if (func_val.isUndef()) return null;
6145 const owner_decl_index = switch (func_val.tag()) {
6146 .extern_fn => func_val.castTag(.extern_fn).?.data.owner_decl,
6147 .function => func_val.castTag(.function).?.data.owner_decl,
6148 .decl_ref => sema.mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data.owner_decl,
6279 if (func_val.isUndef(mod)) return null;
6280 const owner_decl_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
6281 .extern_func => |extern_func| extern_func.decl,
6282 .func => |func| mod.funcPtr(func.index).owner_decl,
6283 .ptr => |ptr| switch (ptr.addr) {
6284 .decl => |decl| mod.declPtr(decl).val.getFunction(mod).?.owner_decl,
6285 else => return null,
6286 },
61496287 else => return null,
61506288 };
6151 return sema.mod.declPtr(owner_decl_index);
6289 return mod.declPtr(owner_decl_index);
61526290}
61536291
61546292pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref {
6293 const mod = sema.mod;
6294 const gpa = sema.gpa;
61556295 const src = sema.src;
61566296
6157 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return .none;
6158 if (!sema.mod.comp.bin_file.options.error_return_tracing) return .none;
6297 if (!mod.backendSupportsFeature(.error_return_trace)) return .none;
6298 if (!mod.comp.bin_file.options.error_return_tracing) return .none;
61596299
61606300 if (block.is_comptime)
61616301 return .none;
......@@ -6168,7 +6308,8 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
61686308 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
61696309 else => |e| return e,
61706310 };
6171 const field_index = sema.structFieldIndex(block, stack_trace_ty, "index", src) catch |err| switch (err) {
6311 const field_name = try mod.intern_pool.getOrPutString(gpa, "index");
6312 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, src) catch |err| switch (err) {
61726313 error.NeededSourceLocation, error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
61736314 else => |e| return e,
61746315 };
......@@ -6191,6 +6332,8 @@ fn popErrorReturnTrace(
61916332 operand: Air.Inst.Ref,
61926333 saved_error_trace_index: Air.Inst.Ref,
61936334) CompileError!void {
6335 const mod = sema.mod;
6336 const gpa = sema.gpa;
61946337 var is_non_error: ?bool = null;
61956338 var is_non_error_inst: Air.Inst.Ref = undefined;
61966339 if (operand != .none) {
......@@ -6205,15 +6348,16 @@ fn popErrorReturnTrace(
62056348
62066349 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
62076350 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
6208 const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty);
6351 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
62096352 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
6210 const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, "index", src, stack_trace_ty, true);
6353 const field_name = try mod.intern_pool.getOrPutString(gpa, "index");
6354 const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true);
62116355 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);
62126356 } else if (is_non_error == null) {
62136357 // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need
62146358 // to pop any error trace that may have been propagated from our arguments.
62156359
6216 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).Struct.fields.len);
6360 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).Struct.fields.len);
62176361 const cond_block_inst = try block.addInstAsIndex(.{
62186362 .tag = .block,
62196363 .data = .{
......@@ -6225,28 +6369,29 @@ fn popErrorReturnTrace(
62256369 });
62266370
62276371 var then_block = block.makeSubBlock();
6228 defer then_block.instructions.deinit(sema.gpa);
6372 defer then_block.instructions.deinit(gpa);
62296373
62306374 // If non-error, then pop the error return trace by restoring the index.
62316375 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
62326376 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
6233 const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty);
6377 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
62346378 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
6235 const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, "index", src, stack_trace_ty, true);
6379 const field_name = try mod.intern_pool.getOrPutString(gpa, "index");
6380 const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true);
62366381 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);
62376382 _ = try then_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);
62386383
62396384 // Otherwise, do nothing
62406385 var else_block = block.makeSubBlock();
6241 defer else_block.instructions.deinit(sema.gpa);
6386 defer else_block.instructions.deinit(gpa);
62426387 _ = try else_block.addBr(cond_block_inst, Air.Inst.Ref.void_value);
62436388
6244 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.CondBr).Struct.fields.len +
6389 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
62456390 then_block.instructions.items.len + else_block.instructions.items.len +
62466391 @typeInfo(Air.Block).Struct.fields.len + 1); // +1 for the sole .cond_br instruction in the .block
62476392
62486393 const cond_br_inst = @intCast(Air.Inst.Index, sema.air_instructions.len);
6249 try sema.air_instructions.append(sema.gpa, .{ .tag = .cond_br, .data = .{ .pl_op = .{
6394 try sema.air_instructions.append(gpa, .{ .tag = .cond_br, .data = .{ .pl_op = .{
62506395 .operand = is_non_error_inst,
62516396 .payload = sema.addExtraAssumeCapacity(Air.CondBr{
62526397 .then_body_len = @intCast(u32, then_block.instructions.items.len),
......@@ -6270,6 +6415,7 @@ fn zirCall(
62706415 const tracy = trace(@src());
62716416 defer tracy.end();
62726417
6418 const mod = sema.mod;
62736419 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
62746420 const callee_src: LazySrcLoc = .{ .node_offset_call_func = inst_data.src_node };
62756421 const call_src = inst_data.src();
......@@ -6288,7 +6434,7 @@ fn zirCall(
62886434 .direct => .{ .direct = try sema.resolveInst(extra.data.callee) },
62896435 .field => blk: {
62906436 const object_ptr = try sema.resolveInst(extra.data.obj_ptr);
6291 const field_name = sema.code.nullTerminatedString(extra.data.field_name_start);
6437 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.data.field_name_start));
62926438 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
62936439 break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src);
62946440 },
......@@ -6320,8 +6466,7 @@ fn zirCall(
63206466 var input_is_error = false;
63216467 const block_index = @intCast(Air.Inst.Index, block.instructions.items.len);
63226468
6323 const func_ty_info = func_ty.fnInfo();
6324 const fn_params_len = func_ty_info.param_types.len;
6469 const fn_params_len = mod.typeToFunc(func_ty).?.param_types.len;
63256470 const parent_comptime = block.is_comptime;
63266471 // `extra_index` and `arg_index` are separate since the bound function is passed as the first argument.
63276472 var extra_index: usize = 0;
......@@ -6330,32 +6475,33 @@ fn zirCall(
63306475 extra_index += 1;
63316476 arg_index += 1;
63326477 }) {
6478 const func_ty_info = mod.typeToFunc(func_ty).?;
63336479 const arg_end = sema.code.extra[extra.end + extra_index];
63346480 defer arg_start = arg_end;
63356481
63366482 // Generate args to comptime params in comptime block.
63376483 defer block.is_comptime = parent_comptime;
6338 if (arg_index < fn_params_len and func_ty_info.comptime_params[arg_index]) {
6484 if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(u5, arg_index))) {
63396485 block.is_comptime = true;
63406486 // TODO set comptime_reason
63416487 }
63426488
63436489 sema.inst_map.putAssumeCapacity(inst, inst: {
63446490 if (arg_index >= fn_params_len)
6345 break :inst Air.Inst.Ref.var_args_param;
6491 break :inst Air.Inst.Ref.var_args_param_type;
63466492
6347 if (func_ty_info.param_types[arg_index].tag() == .generic_poison)
6493 if (func_ty_info.param_types[arg_index] == .generic_poison_type)
63486494 break :inst Air.Inst.Ref.generic_poison_type;
63496495
6350 break :inst try sema.addType(func_ty_info.param_types[arg_index]);
6496 break :inst try sema.addType(func_ty_info.param_types[arg_index].toType());
63516497 });
63526498
63536499 const resolved = try sema.resolveBody(block, args_body[arg_start..arg_end], inst);
63546500 const resolved_ty = sema.typeOf(resolved);
6355 if (resolved_ty.zigTypeTag() == .NoReturn) {
6501 if (resolved_ty.zigTypeTag(mod) == .NoReturn) {
63566502 return resolved;
63576503 }
6358 if (resolved_ty.isError()) {
6504 if (resolved_ty.isError(mod)) {
63596505 input_is_error = true;
63606506 }
63616507 resolved_args[arg_index] = resolved;
......@@ -6367,7 +6513,7 @@ fn zirCall(
63676513 // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction.
63686514 const call_dbg_node = inst - 1;
63696515
6370 if (sema.mod.backendSupportsFeature(.error_return_trace) and sema.mod.comp.bin_file.options.error_return_tracing and
6516 if (mod.backendSupportsFeature(.error_return_trace) and mod.comp.bin_file.options.error_return_tracing and
63716517 !block.is_comptime and !block.is_typeof and (input_is_error or pop_error_return_trace))
63726518 {
63736519 const call_inst: Air.Inst.Ref = if (modifier == .always_tail) undefined else b: {
......@@ -6375,15 +6521,16 @@ fn zirCall(
63756521 };
63766522
63776523 const return_ty = sema.typeOf(call_inst);
6378 if (modifier != .always_tail and return_ty.isNoReturn())
6524 if (modifier != .always_tail and return_ty.isNoReturn(mod))
63796525 return call_inst; // call to "fn(...) noreturn", don't pop
63806526
63816527 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only
63826528 // need to clean-up our own trace if we were passed to a non-error-handling expression.
6383 if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError())) {
6529 if (input_is_error or (pop_error_return_trace and modifier != .always_tail and return_ty.isError(mod))) {
63846530 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
63856531 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
6386 const field_index = try sema.structFieldIndex(block, stack_trace_ty, "index", call_src);
6532 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index");
6533 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
63876534
63886535 // Insert a save instruction before the arg resolution + call instructions we just generated
63896536 const save_inst = try block.insertInst(block_index, .{
......@@ -6417,24 +6564,24 @@ fn checkCallArgumentCount(
64176564 total_args: usize,
64186565 member_fn: bool,
64196566) !Type {
6567 const mod = sema.mod;
64206568 const func_ty = func_ty: {
6421 switch (callee_ty.zigTypeTag()) {
6569 switch (callee_ty.zigTypeTag(mod)) {
64226570 .Fn => break :func_ty callee_ty,
64236571 .Pointer => {
6424 const ptr_info = callee_ty.ptrInfo().data;
6425 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {
6572 const ptr_info = callee_ty.ptrInfo(mod);
6573 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Fn) {
64266574 break :func_ty ptr_info.pointee_type;
64276575 }
64286576 },
64296577 .Optional => {
6430 var buf: Type.Payload.ElemType = undefined;
6431 const opt_child = callee_ty.optionalChild(&buf);
6432 if (opt_child.zigTypeTag() == .Fn or (opt_child.isSinglePointer() and
6433 opt_child.childType().zigTypeTag() == .Fn))
6578 const opt_child = callee_ty.optionalChild(mod);
6579 if (opt_child.zigTypeTag(mod) == .Fn or (opt_child.isSinglePointer(mod) and
6580 opt_child.childType(mod).zigTypeTag(mod) == .Fn))
64346581 {
64356582 const msg = msg: {
64366583 const msg = try sema.errMsg(block, func_src, "cannot call optional type '{}'", .{
6437 callee_ty.fmt(sema.mod),
6584 callee_ty.fmt(mod),
64386585 });
64396586 errdefer msg.destroy(sema.gpa);
64406587 try sema.errNote(block, func_src, msg, "consider using '.?', 'orelse' or 'if'", .{});
......@@ -6445,10 +6592,10 @@ fn checkCallArgumentCount(
64456592 },
64466593 else => {},
64476594 }
6448 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(sema.mod)});
6595 return sema.fail(block, func_src, "type '{}' not a function", .{callee_ty.fmt(mod)});
64496596 };
64506597
6451 const func_ty_info = func_ty.fnInfo();
6598 const func_ty_info = mod.typeToFunc(func_ty).?;
64526599 const fn_params_len = func_ty_info.param_types.len;
64536600 const args_len = total_args - @boolToInt(member_fn);
64546601 if (func_ty_info.is_var_args) {
......@@ -6475,7 +6622,7 @@ fn checkCallArgumentCount(
64756622 );
64766623 errdefer msg.destroy(sema.gpa);
64776624
6478 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{});
6625 if (maybe_decl) |fn_decl| try mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{});
64796626 break :msg msg;
64806627 };
64816628 return sema.failWithOwnedErrorMsg(msg);
......@@ -6488,22 +6635,23 @@ fn callBuiltin(
64886635 modifier: std.builtin.CallModifier,
64896636 args: []const Air.Inst.Ref,
64906637) !void {
6638 const mod = sema.mod;
64916639 const callee_ty = sema.typeOf(builtin_fn);
64926640 const func_ty = func_ty: {
6493 switch (callee_ty.zigTypeTag()) {
6641 switch (callee_ty.zigTypeTag(mod)) {
64946642 .Fn => break :func_ty callee_ty,
64956643 .Pointer => {
6496 const ptr_info = callee_ty.ptrInfo().data;
6497 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Fn) {
6644 const ptr_info = callee_ty.ptrInfo(mod);
6645 if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag(mod) == .Fn) {
64986646 break :func_ty ptr_info.pointee_type;
64996647 }
65006648 },
65016649 else => {},
65026650 }
6503 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(sema.mod)});
6651 std.debug.panic("type '{}' is not a function calling builtin fn", .{callee_ty.fmt(mod)});
65046652 };
65056653
6506 const func_ty_info = func_ty.fnInfo();
6654 const func_ty_info = mod.typeToFunc(func_ty).?;
65076655 const fn_params_len = func_ty_info.param_types.len;
65086656 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) {
65096657 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len });
......@@ -6511,76 +6659,6 @@ fn callBuiltin(
65116659 _ = try sema.analyzeCall(block, builtin_fn, func_ty, sema.src, sema.src, modifier, false, args, null, null);
65126660}
65136661
6514const GenericCallAdapter = struct {
6515 generic_fn: *Module.Fn,
6516 precomputed_hash: u64,
6517 func_ty_info: Type.Payload.Function.Data,
6518 args: []const Arg,
6519 module: *Module,
6520
6521 const Arg = struct {
6522 ty: Type,
6523 val: Value,
6524 is_anytype: bool,
6525 };
6526
6527 pub fn eql(ctx: @This(), adapted_key: void, other_key: *Module.Fn) bool {
6528 _ = adapted_key;
6529 // Checking for equality may happen on an item that has been inserted
6530 // into the map but is not yet fully initialized. In such case, the
6531 // two initialized fields are `hash` and `generic_owner_decl`.
6532 if (ctx.generic_fn.owner_decl != other_key.generic_owner_decl.unwrap().?) return false;
6533
6534 const other_comptime_args = other_key.comptime_args.?;
6535 for (other_comptime_args[0..ctx.func_ty_info.param_types.len], 0..) |other_arg, i| {
6536 const this_arg = ctx.args[i];
6537 const this_is_comptime = this_arg.val.tag() != .generic_poison;
6538 const other_is_comptime = other_arg.val.tag() != .generic_poison;
6539 const this_is_anytype = this_arg.is_anytype;
6540 const other_is_anytype = other_key.isAnytypeParam(ctx.module, @intCast(u32, i));
6541
6542 if (other_is_anytype != this_is_anytype) return false;
6543 if (other_is_comptime != this_is_comptime) return false;
6544
6545 if (this_is_anytype) {
6546 // Both are anytype parameters.
6547 if (!this_arg.ty.eql(other_arg.ty, ctx.module)) {
6548 return false;
6549 }
6550 if (this_is_comptime) {
6551 // Both are comptime and anytype parameters with matching types.
6552 if (!this_arg.val.eql(other_arg.val, other_arg.ty, ctx.module)) {
6553 return false;
6554 }
6555 }
6556 } else if (this_is_comptime) {
6557 // Both are comptime parameters but not anytype parameters.
6558 // We assert no error is possible here because any lazy values must be resolved
6559 // before inserting into the generic function hash map.
6560 const is_eql = Value.eqlAdvanced(
6561 this_arg.val,
6562 this_arg.ty,
6563 other_arg.val,
6564 other_arg.ty,
6565 ctx.module,
6566 null,
6567 ) catch unreachable;
6568 if (!is_eql) {
6569 return false;
6570 }
6571 }
6572 }
6573 return true;
6574 }
6575
6576 /// The implementation of the hash is in semantic analysis of function calls, so
6577 /// that any errors when computing the hash can be properly reported.
6578 pub fn hash(ctx: @This(), adapted_key: void) u64 {
6579 _ = adapted_key;
6580 return ctx.precomputed_hash;
6581 }
6582};
6583
65846662fn analyzeCall(
65856663 sema: *Sema,
65866664 block: *Block,
......@@ -6597,7 +6675,7 @@ fn analyzeCall(
65976675 const mod = sema.mod;
65986676
65996677 const callee_ty = sema.typeOf(func);
6600 const func_ty_info = func_ty.fnInfo();
6678 const func_ty_info = mod.typeToFunc(func_ty).?;
66016679 const fn_params_len = func_ty_info.param_types.len;
66026680 const cc = func_ty_info.cc;
66036681 if (cc == .Naked) {
......@@ -6611,7 +6689,7 @@ fn analyzeCall(
66116689 );
66126690 errdefer msg.destroy(sema.gpa);
66136691
6614 if (maybe_decl) |fn_decl| try sema.mod.errNoteNonLazy(fn_decl.srcLoc(), msg, "function declared here", .{});
6692 if (maybe_decl) |fn_decl| try mod.errNoteNonLazy(fn_decl.srcLoc(mod), msg, "function declared here", .{});
66156693 break :msg msg;
66166694 };
66176695 return sema.failWithOwnedErrorMsg(msg);
......@@ -6645,7 +6723,7 @@ fn analyzeCall(
66456723 var comptime_reason_buf: Block.ComptimeReason = undefined;
66466724 var comptime_reason: ?*const Block.ComptimeReason = null;
66476725 if (!is_comptime_call) {
6648 if (sema.typeRequiresComptime(func_ty_info.return_type)) |ct| {
6726 if (sema.typeRequiresComptime(func_ty_info.return_type.toType())) |ct| {
66496727 is_comptime_call = ct;
66506728 if (ct) {
66516729 // stage1 can't handle doing this directly
......@@ -6653,7 +6731,7 @@ fn analyzeCall(
66536731 .block = block,
66546732 .func = func,
66556733 .func_src = func_src,
6656 .return_ty = func_ty_info.return_type,
6734 .return_ty = func_ty_info.return_type.toType(),
66576735 } };
66586736 comptime_reason = &comptime_reason_buf;
66596737 }
......@@ -6671,7 +6749,7 @@ fn analyzeCall(
66716749 func,
66726750 func_src,
66736751 call_src,
6674 func_ty_info,
6752 func_ty,
66756753 ensure_result_used,
66766754 uncasted_args,
66776755 call_tag,
......@@ -6691,7 +6769,7 @@ fn analyzeCall(
66916769 .block = block,
66926770 .func = func,
66936771 .func_src = func_src,
6694 .return_ty = func_ty_info.return_type,
6772 .return_ty = func_ty_info.return_type.toType(),
66956773 } };
66966774 comptime_reason = &comptime_reason_buf;
66976775 },
......@@ -6708,18 +6786,21 @@ fn analyzeCall(
67086786 if (err == error.AnalysisFail and comptime_reason != null) try comptime_reason.?.explain(sema, sema.err);
67096787 return err;
67106788 };
6711 const module_fn = switch (func_val.tag()) {
6712 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,
6713 .function => func_val.castTag(.function).?.data,
6714 .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{
6789 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
6790 .extern_func => return sema.fail(block, call_src, "{s} call of extern function", .{
67156791 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
67166792 }),
6717 else => {
6718 assert(callee_ty.isPtrAtRuntime());
6719 return sema.fail(block, call_src, "{s} call of function pointer", .{
6720 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6721 });
6793 .func => |function| function.index,
6794 .ptr => |ptr| switch (ptr.addr) {
6795 .decl => |decl| mod.declPtr(decl).val.getFunctionIndex(mod).unwrap().?,
6796 else => {
6797 assert(callee_ty.isPtrAtRuntime(mod));
6798 return sema.fail(block, call_src, "{s} call of function pointer", .{
6799 @as([]const u8, if (is_comptime_call) "comptime" else "inline"),
6800 });
6801 },
67226802 },
6803 else => unreachable,
67236804 };
67246805 if (func_ty_info.is_var_args) {
67256806 return sema.fail(block, call_src, "{s} call of variadic function", .{
......@@ -6752,8 +6833,9 @@ fn analyzeCall(
67526833 // In order to save a bit of stack space, directly modify Sema rather
67536834 // than create a child one.
67546835 const parent_zir = sema.code;
6836 const module_fn = mod.funcPtr(module_fn_index);
67556837 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
6756 sema.code = fn_owner_decl.getFileScope().zir;
6838 sema.code = fn_owner_decl.getFileScope(mod).zir;
67576839 defer sema.code = parent_zir;
67586840
67596841 try mod.declareDeclDependencyType(sema.owner_decl_index, module_fn.owner_decl, .function_body);
......@@ -6767,14 +6849,17 @@ fn analyzeCall(
67676849 }
67686850
67696851 const parent_func = sema.func;
6852 const parent_func_index = sema.func_index;
67706853 sema.func = module_fn;
6854 sema.func_index = module_fn_index.toOptional();
67716855 defer sema.func = parent_func;
6856 defer sema.func_index = parent_func_index;
67726857
67736858 const parent_err_ret_index = sema.error_return_trace_index_on_fn_entry;
67746859 sema.error_return_trace_index_on_fn_entry = block.error_return_trace_index;
67756860 defer sema.error_return_trace_index_on_fn_entry = parent_err_ret_index;
67766861
6777 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, fn_owner_decl.src_scope);
6862 var wip_captures = try WipCaptureScope.init(gpa, fn_owner_decl.src_scope);
67786863 defer wip_captures.deinit();
67796864
67806865 var child_block: Block = .{
......@@ -6797,28 +6882,18 @@ fn analyzeCall(
67976882 defer child_block.instructions.deinit(gpa);
67986883 defer merges.deinit(gpa);
67996884
6800 // If it's a comptime function call, we need to memoize it as long as no external
6801 // comptime memory is mutated.
6802 var memoized_call_key: Module.MemoizedCall.Key = undefined;
6803 var delete_memoized_call_key = false;
6804 defer if (delete_memoized_call_key) gpa.free(memoized_call_key.args);
6805 if (is_comptime_call) {
6806 memoized_call_key = .{
6807 .func = module_fn,
6808 .args = try gpa.alloc(TypedValue, func_ty_info.param_types.len),
6809 };
6810 delete_memoized_call_key = true;
6811 }
6812
68136885 try sema.emitBackwardBranch(block, call_src);
68146886
6815 // Whether this call should be memoized, set to false if the call can mutate
6816 // comptime state.
6887 // Whether this call should be memoized, set to false if the call can mutate comptime state.
68176888 var should_memoize = true;
68186889
6819 var new_fn_info = fn_owner_decl.ty.fnInfo();
6820 new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len);
6821 new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr;
6890 // If it's a comptime function call, we need to memoize it as long as no external
6891 // comptime memory is mutated.
6892 const memoized_arg_values = try sema.arena.alloc(InternPool.Index, func_ty_info.param_types.len);
6893
6894 var new_fn_info = mod.typeToFunc(fn_owner_decl.ty).?;
6895 new_fn_info.param_types = try sema.arena.alloc(InternPool.Index, new_fn_info.param_types.len);
6896 new_fn_info.comptime_bits = 0;
68226897
68236898 // This will have return instructions analyzed as break instructions to
68246899 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
......@@ -6837,31 +6912,31 @@ fn analyzeCall(
68376912 &child_block,
68386913 .unneeded,
68396914 inst,
6840 new_fn_info,
6915 &new_fn_info,
68416916 &arg_i,
68426917 uncasted_args,
68436918 is_comptime_call,
68446919 &should_memoize,
6845 memoized_call_key,
6846 func_ty_info.param_types,
6920 memoized_arg_values,
6921 mod.typeToFunc(func_ty).?.param_types,
68476922 func,
68486923 &has_comptime_args,
68496924 ) catch |err| switch (err) {
68506925 error.NeededSourceLocation => {
68516926 _ = sema.inst_map.remove(inst);
6852 const decl = sema.mod.declPtr(block.src_decl);
6927 const decl = mod.declPtr(block.src_decl);
68536928 try sema.analyzeInlineCallArg(
68546929 block,
68556930 &child_block,
6856 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src),
6931 mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src),
68576932 inst,
6858 new_fn_info,
6933 &new_fn_info,
68596934 &arg_i,
68606935 uncasted_args,
68616936 is_comptime_call,
68626937 &should_memoize,
6863 memoized_call_key,
6864 func_ty_info.param_types,
6938 memoized_arg_values,
6939 mod.typeToFunc(func_ty).?.param_types,
68656940 func,
68666941 &has_comptime_args,
68676942 );
......@@ -6897,21 +6972,15 @@ fn analyzeCall(
68976972 // Create a fresh inferred error set type for inline/comptime calls.
68986973 const fn_ret_ty = blk: {
68996974 if (module_fn.hasInferredErrorSet(mod)) {
6900 const node = try sema.gpa.create(Module.Fn.InferredErrorSetListNode);
6901 node.data = .{ .func = module_fn };
6902 if (parent_func) |some| {
6903 some.inferred_error_sets.prepend(node);
6904 }
6905
6906 const error_set_ty = try Type.Tag.error_set_inferred.create(sema.arena, &node.data);
6907 break :blk try Type.Tag.error_union.create(sema.arena, .{
6908 .error_set = error_set_ty,
6909 .payload = bare_return_type,
6975 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
6976 .func = module_fn_index,
69106977 });
6978 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
6979 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
69116980 }
69126981 break :blk bare_return_type;
69136982 };
6914 new_fn_info.return_type = fn_ret_ty;
6983 new_fn_info.return_type = fn_ret_ty.toIntern();
69156984 const parent_fn_ret_ty = sema.fn_ret_ty;
69166985 sema.fn_ret_ty = fn_ret_ty;
69176986 defer sema.fn_ret_ty = parent_fn_ret_ty;
......@@ -6920,23 +6989,22 @@ fn analyzeCall(
69206989 // bug generating invalid LLVM IR.
69216990 const res2: Air.Inst.Ref = res2: {
69226991 if (should_memoize and is_comptime_call) {
6923 if (mod.memoized_calls.getContext(memoized_call_key, .{ .module = mod })) |result| {
6924 const ty_inst = try sema.addType(fn_ret_ty);
6925 try sema.air_values.append(gpa, result.val);
6926 sema.air_instructions.set(block_inst, .{
6927 .tag = .constant,
6928 .data = .{ .ty_pl = .{
6929 .ty = ty_inst,
6930 .payload = @intCast(u32, sema.air_values.items.len - 1),
6931 } },
6932 });
6933 break :res2 Air.indexToRef(block_inst);
6992 if (mod.intern_pool.getIfExists(.{ .memoized_call = .{
6993 .func = module_fn_index,
6994 .arg_values = memoized_arg_values,
6995 .result = .none,
6996 } })) |memoized_call_index| {
6997 const memoized_call = mod.intern_pool.indexToKey(memoized_call_index).memoized_call;
6998 break :res2 try sema.addConstant(
6999 mod.intern_pool.typeOf(memoized_call.result).toType(),
7000 memoized_call.result.toValue(),
7001 );
69347002 }
69357003 }
69367004
6937 const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info);
7005 const new_func_resolved_ty = try mod.funcType(new_fn_info);
69387006 if (!is_comptime_call and !block.is_typeof) {
6939 try sema.emitDbgInline(block, parent_func.?, module_fn, new_func_resolved_ty, .dbg_inline_begin);
7007 try sema.emitDbgInline(block, parent_func_index.unwrap().?, module_fn_index, new_func_resolved_ty, .dbg_inline_begin);
69407008
69417009 const zir_tags = sema.code.instructions.items(.tag);
69427010 for (fn_info.param_body) |param| switch (zir_tags[param]) {
......@@ -6968,7 +7036,7 @@ fn analyzeCall(
69687036 error.ComptimeReturn => break :result inlining.comptime_result,
69697037 error.AnalysisFail => {
69707038 const err_msg = sema.err orelse return err;
6971 if (std.mem.eql(u8, err_msg.msg, recursive_msg)) return err;
7039 if (mem.eql(u8, err_msg.msg, recursive_msg)) return err;
69727040 try sema.errNote(block, call_src, err_msg, "called from here", .{});
69737041 err_msg.clearTrace(sema.gpa);
69747042 return err;
......@@ -6978,11 +7046,11 @@ fn analyzeCall(
69787046 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
69797047 };
69807048
6981 if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag() != .NoReturn) {
7049 if (!is_comptime_call and !block.is_typeof and sema.typeOf(result).zigTypeTag(mod) != .NoReturn) {
69827050 try sema.emitDbgInline(
69837051 block,
6984 module_fn,
6985 parent_func.?,
7052 module_fn_index,
7053 parent_func_index.unwrap().?,
69867054 mod.declPtr(parent_func.?.owner_decl).ty,
69877055 .dbg_inline_end,
69887056 );
......@@ -6993,23 +7061,11 @@ fn analyzeCall(
69937061
69947062 // TODO: check whether any external comptime memory was mutated by the
69957063 // comptime function call. If so, then do not memoize the call here.
6996 // TODO: re-evaluate whether memoized_calls needs its own arena. I think
6997 // it should be fine to use the Decl arena for the function.
6998 {
6999 var arena_allocator = std.heap.ArenaAllocator.init(gpa);
7000 errdefer arena_allocator.deinit();
7001 const arena = arena_allocator.allocator();
7002
7003 for (memoized_call_key.args) |*arg| {
7004 arg.* = try arg.*.copy(arena);
7005 }
7006
7007 try mod.memoized_calls.putContext(gpa, memoized_call_key, .{
7008 .val = try result_val.copy(arena),
7009 .arena = arena_allocator.state,
7010 }, .{ .module = mod });
7011 delete_memoized_call_key = false;
7012 }
7064 _ = try mod.intern(.{ .memoized_call = .{
7065 .func = module_fn_index,
7066 .arg_values = memoized_arg_values,
7067 .result = try result_val.intern(fn_ret_ty, mod),
7068 } });
70137069 }
70147070
70157071 break :res2 result;
......@@ -7028,7 +7084,7 @@ fn analyzeCall(
70287084 .func_inst = func,
70297085 .param_i = @intCast(u32, i),
70307086 } };
7031 const param_ty = func_ty.fnParamType(i);
7087 const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType();
70327088 args[i] = sema.analyzeCallArg(
70337089 block,
70347090 .unneeded,
......@@ -7037,10 +7093,10 @@ fn analyzeCall(
70377093 opts,
70387094 ) catch |err| switch (err) {
70397095 error.NeededSourceLocation => {
7040 const decl = sema.mod.declPtr(block.src_decl);
7096 const decl = mod.declPtr(block.src_decl);
70417097 _ = try sema.analyzeCallArg(
70427098 block,
7043 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src),
7099 mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src),
70447100 param_ty,
70457101 uncasted_arg,
70467102 opts,
......@@ -7052,11 +7108,11 @@ fn analyzeCall(
70527108 } else {
70537109 args[i] = sema.coerceVarArgParam(block, uncasted_arg, .unneeded) catch |err| switch (err) {
70547110 error.NeededSourceLocation => {
7055 const decl = sema.mod.declPtr(block.src_decl);
7111 const decl = mod.declPtr(block.src_decl);
70567112 _ = try sema.coerceVarArgParam(
70577113 block,
70587114 uncasted_arg,
7059 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src),
7115 mod.argSrc(call_src.node_offset.x, decl, i, bound_arg_src),
70607116 );
70617117 unreachable;
70627118 },
......@@ -7067,14 +7123,14 @@ fn analyzeCall(
70677123
70687124 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
70697125
7070 try sema.queueFullTypeResolution(func_ty_info.return_type);
7071 if (sema.owner_func != null and func_ty_info.return_type.isError()) {
7126 try sema.queueFullTypeResolution(func_ty_info.return_type.toType());
7127 if (sema.owner_func != null and func_ty_info.return_type.toType().isError(mod)) {
70727128 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
70737129 }
70747130
70757131 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7076 if (func_val.castTag(.function)) |func_obj| {
7077 try sema.mod.ensureFuncBodyAnalysisQueued(func_obj.data);
7132 if (mod.intern_pool.indexToFunc(func_val.toIntern()).unwrap()) |func_index| {
7133 try mod.ensureFuncBodyAnalysisQueued(func_index);
70787134 }
70797135 }
70807136
......@@ -7096,23 +7152,24 @@ fn analyzeCall(
70967152 try sema.ensureResultUsed(block, sema.typeOf(func_inst), call_src);
70977153 }
70987154 return sema.handleTailCall(block, call_src, func_ty, func_inst);
7099 } else if (block.wantSafety() and func_ty_info.return_type.isNoReturn()) {
7155 }
7156 if (block.wantSafety() and func_ty_info.return_type == .noreturn_type) skip_safety: {
71007157 // Function pointers and extern functions aren't guaranteed to
71017158 // actually be noreturn so we add a safety check for them.
7102 check: {
7103 var func_val = (try sema.resolveMaybeUndefVal(func)) orelse break :check;
7104 switch (func_val.tag()) {
7105 .function, .decl_ref => {
7106 _ = try block.addNoOp(.unreach);
7107 return Air.Inst.Ref.unreachable_value;
7159 if (try sema.resolveMaybeUndefVal(func)) |func_val| {
7160 switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7161 .func => break :skip_safety,
7162 .ptr => |ptr| switch (ptr.addr) {
7163 .decl => |decl| if (!mod.declPtr(decl).isExtern(mod)) break :skip_safety,
7164 else => {},
71087165 },
7109 else => break :check,
7166 else => {},
71107167 }
71117168 }
7112
71137169 try sema.safetyPanic(block, .noreturn_returned);
71147170 return Air.Inst.Ref.unreachable_value;
7115 } else if (func_ty_info.return_type.isNoReturn()) {
7171 }
7172 if (func_ty_info.return_type == .noreturn_type) {
71167173 _ = try block.addNoOp(.unreach);
71177174 return Air.Inst.Ref.unreachable_value;
71187175 }
......@@ -7126,17 +7183,18 @@ fn analyzeCall(
71267183}
71277184
71287185fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref {
7129 const target = sema.mod.getTarget();
7130 const backend = sema.mod.comp.getZigBackend();
7186 const mod = sema.mod;
7187 const target = mod.getTarget();
7188 const backend = mod.comp.getZigBackend();
71317189 if (!target_util.supportsTailCall(target, backend)) {
71327190 return sema.fail(block, call_src, "unable to perform tail call: compiler backend '{s}' does not support tail calls on target architecture '{s}' with the selected CPU feature flags", .{
71337191 @tagName(backend), @tagName(target.cpu.arch),
71347192 });
71357193 }
7136 const func_decl = sema.mod.declPtr(sema.owner_func.?.owner_decl);
7137 if (!func_ty.eql(func_decl.ty, sema.mod)) {
7194 const func_decl = mod.declPtr(sema.owner_func.?.owner_decl);
7195 if (!func_ty.eql(func_decl.ty, mod)) {
71387196 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{}' does not match type of calling function '{}'", .{
7139 func_ty.fmt(sema.mod), func_decl.ty.fmt(sema.mod),
7197 func_ty.fmt(mod), func_decl.ty.fmt(mod),
71407198 });
71417199 }
71427200 _ = try block.addUnOp(.ret, result);
......@@ -7149,16 +7207,17 @@ fn analyzeInlineCallArg(
71497207 param_block: *Block,
71507208 arg_src: LazySrcLoc,
71517209 inst: Zir.Inst.Index,
7152 new_fn_info: Type.Payload.Function.Data,
7210 new_fn_info: *InternPool.Key.FuncType,
71537211 arg_i: *usize,
71547212 uncasted_args: []const Air.Inst.Ref,
71557213 is_comptime_call: bool,
71567214 should_memoize: *bool,
7157 memoized_call_key: Module.MemoizedCall.Key,
7158 raw_param_types: []const Type,
7215 memoized_arg_values: []InternPool.Index,
7216 raw_param_types: []const InternPool.Index,
71597217 func_inst: Air.Inst.Ref,
71607218 has_comptime_args: *bool,
71617219) !void {
7220 const mod = sema.mod;
71627221 const zir_tags = sema.code.instructions.items(.tag);
71637222 switch (zir_tags[inst]) {
71647223 .param_comptime, .param_anytype_comptime => has_comptime_args.* = true,
......@@ -7174,13 +7233,14 @@ fn analyzeInlineCallArg(
71747233 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
71757234 const param_ty = param_ty: {
71767235 const raw_param_ty = raw_param_types[arg_i.*];
7177 if (raw_param_ty.tag() != .generic_poison) break :param_ty raw_param_ty;
7236 if (raw_param_ty != .generic_poison_type) break :param_ty raw_param_ty;
71787237 const param_ty_inst = try sema.resolveBody(param_block, param_body, inst);
7179 break :param_ty try sema.analyzeAsType(param_block, param_src, param_ty_inst);
7238 const param_ty = try sema.analyzeAsType(param_block, param_src, param_ty_inst);
7239 break :param_ty param_ty.toIntern();
71807240 };
71817241 new_fn_info.param_types[arg_i.*] = param_ty;
71827242 const uncasted_arg = uncasted_args[arg_i.*];
7183 if (try sema.typeRequiresComptime(param_ty)) {
7243 if (try sema.typeRequiresComptime(param_ty.toType())) {
71847244 _ = sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "argument to parameter with comptime-only type must be comptime-known") catch |err| {
71857245 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
71867246 return err;
......@@ -7188,7 +7248,7 @@ fn analyzeInlineCallArg(
71887248 } else if (!is_comptime_call and zir_tags[inst] == .param_comptime) {
71897249 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
71907250 }
7191 const casted_arg = sema.coerceExtra(arg_block, param_ty, uncasted_arg, arg_src, .{ .param_src = .{
7251 const casted_arg = sema.coerceExtra(arg_block, param_ty.toType(), uncasted_arg, arg_src, .{ .param_src = .{
71927252 .func_inst = func_inst,
71937253 .param_i = @intCast(u32, arg_i.*),
71947254 } }) catch |err| switch (err) {
......@@ -7202,24 +7262,20 @@ fn analyzeInlineCallArg(
72027262 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
72037263 return err;
72047264 };
7205 switch (arg_val.tag()) {
7265 switch (arg_val.toIntern()) {
72067266 .generic_poison, .generic_poison_type => {
72077267 // This function is currently evaluated as part of an as-of-yet unresolvable
72087268 // parameter or return type.
72097269 return error.GenericPoison;
72107270 },
7211 else => {
7212 // Needed so that lazy values do not trigger
7213 // assertion due to type not being resolved
7214 // when the hash function is called.
7215 try sema.resolveLazyValue(arg_val);
7216 },
7271 else => {},
72177272 }
7218 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
7219 memoized_call_key.args[arg_i.*] = .{
7220 .ty = param_ty,
7221 .val = arg_val,
7222 };
7273 // Needed so that lazy values do not trigger
7274 // assertion due to type not being resolved
7275 // when the hash function is called.
7276 const resolved_arg_val = try sema.resolveLazyValue(arg_val);
7277 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);
7278 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(param_ty.toType(), mod);
72237279 } else {
72247280 sema.inst_map.putAssumeCapacityNoClobber(inst, casted_arg);
72257281 }
......@@ -7233,7 +7289,7 @@ fn analyzeInlineCallArg(
72337289 .param_anytype, .param_anytype_comptime => {
72347290 // No coercion needed.
72357291 const uncasted_arg = uncasted_args[arg_i.*];
7236 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg);
7292 new_fn_info.param_types[arg_i.*] = sema.typeOf(uncasted_arg).toIntern();
72377293
72387294 if (is_comptime_call) {
72397295 sema.inst_map.putAssumeCapacityNoClobber(inst, uncasted_arg);
......@@ -7241,24 +7297,20 @@ fn analyzeInlineCallArg(
72417297 if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err);
72427298 return err;
72437299 };
7244 switch (arg_val.tag()) {
7300 switch (arg_val.toIntern()) {
72457301 .generic_poison, .generic_poison_type => {
72467302 // This function is currently evaluated as part of an as-of-yet unresolvable
72477303 // parameter or return type.
72487304 return error.GenericPoison;
72497305 },
7250 else => {
7251 // Needed so that lazy values do not trigger
7252 // assertion due to type not being resolved
7253 // when the hash function is called.
7254 try sema.resolveLazyValue(arg_val);
7255 },
7306 else => {},
72567307 }
7257 should_memoize.* = should_memoize.* and !arg_val.canMutateComptimeVarState();
7258 memoized_call_key.args[arg_i.*] = .{
7259 .ty = sema.typeOf(uncasted_arg),
7260 .val = arg_val,
7261 };
7308 // Needed so that lazy values do not trigger
7309 // assertion due to type not being resolved
7310 // when the hash function is called.
7311 const resolved_arg_val = try sema.resolveLazyValue(arg_val);
7312 should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod);
7313 memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(sema.typeOf(uncasted_arg), mod);
72627314 } else {
72637315 if (zir_tags[inst] == .param_anytype_comptime) {
72647316 _ = try sema.resolveConstMaybeUndefVal(arg_block, arg_src, uncasted_arg, "parameter is comptime");
......@@ -7298,14 +7350,15 @@ fn analyzeGenericCallArg(
72987350 uncasted_arg: Air.Inst.Ref,
72997351 comptime_arg: TypedValue,
73007352 runtime_args: []Air.Inst.Ref,
7301 new_fn_info: Type.Payload.Function.Data,
7353 new_fn_info: InternPool.Key.FuncType,
73027354 runtime_i: *u32,
73037355) !void {
7304 const is_runtime = comptime_arg.val.tag() == .generic_poison and
7305 comptime_arg.ty.hasRuntimeBits() and
7356 const mod = sema.mod;
7357 const is_runtime = comptime_arg.val.isGenericPoison() and
7358 comptime_arg.ty.hasRuntimeBits(mod) and
73067359 !(try sema.typeRequiresComptime(comptime_arg.ty));
73077360 if (is_runtime) {
7308 const param_ty = new_fn_info.param_types[runtime_i.*];
7361 const param_ty = new_fn_info.param_types[runtime_i.*].toType();
73097362 const casted_arg = try sema.coerce(block, param_ty, uncasted_arg, arg_src);
73107363 try sema.queueFullTypeResolution(param_ty);
73117364 runtime_args[runtime_i.*] = casted_arg;
......@@ -7315,10 +7368,16 @@ fn analyzeGenericCallArg(
73157368 }
73167369}
73177370
7318fn analyzeGenericCallArgVal(sema: *Sema, block: *Block, arg_src: LazySrcLoc, uncasted_arg: Air.Inst.Ref) !Value {
7319 const arg_val = try sema.resolveValue(block, arg_src, uncasted_arg, "parameter is comptime");
7320 try sema.resolveLazyValue(arg_val);
7321 return arg_val;
7371fn analyzeGenericCallArgVal(
7372 sema: *Sema,
7373 block: *Block,
7374 arg_src: LazySrcLoc,
7375 arg_ty: Type,
7376 uncasted_arg: Air.Inst.Ref,
7377 reason: []const u8,
7378) !Value {
7379 const casted_arg = try sema.coerce(block, arg_ty, uncasted_arg, arg_src);
7380 return sema.resolveLazyValue(try sema.resolveValue(block, arg_src, casted_arg, reason));
73227381}
73237382
73247383fn instantiateGenericCall(
......@@ -7327,7 +7386,7 @@ fn instantiateGenericCall(
73277386 func: Air.Inst.Ref,
73287387 func_src: LazySrcLoc,
73297388 call_src: LazySrcLoc,
7330 func_ty_info: Type.Payload.Function.Data,
7389 generic_func_ty: Type,
73317390 ensure_result_used: bool,
73327391 uncasted_args: []const Air.Inst.Ref,
73337392 call_tag: Air.Inst.Tag,
......@@ -7338,46 +7397,41 @@ fn instantiateGenericCall(
73387397 const gpa = sema.gpa;
73397398
73407399 const func_val = try sema.resolveConstValue(block, func_src, func, "generic function being called must be comptime-known");
7341 const module_fn = switch (func_val.tag()) {
7342 .function => func_val.castTag(.function).?.data,
7343 .decl_ref => mod.declPtr(func_val.castTag(.decl_ref).?.data).val.castTag(.function).?.data,
7400 const module_fn_index = switch (mod.intern_pool.indexToKey(func_val.toIntern())) {
7401 .func => |function| function.index,
7402 .ptr => |ptr| mod.declPtr(ptr.addr.decl).val.getFunctionIndex(mod).unwrap().?,
73447403 else => unreachable,
73457404 };
7405 const module_fn = mod.funcPtr(module_fn_index);
73467406 // Check the Module's generic function map with an adapted context, so that we
73477407 // can match against `uncasted_args` rather than doing the work below to create a
73487408 // generic Scope only to junk it if it matches an existing instantiation.
73497409 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
7350 const namespace = fn_owner_decl.src_namespace;
7410 const namespace_index = fn_owner_decl.src_namespace;
7411 const namespace = mod.namespacePtr(namespace_index);
73517412 const fn_zir = namespace.file_scope.zir;
73527413 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
73537414 const zir_tags = fn_zir.instructions.items(.tag);
73547415
7355 // This hash must match `Module.MonomorphedFuncsContext.hash`.
7356 // For parameters explicitly marked comptime and simple parameter type expressions,
7357 // we know whether a parameter is elided from a monomorphed function, and can
7358 // use it in the hash here. However, for parameter type expressions that are not
7359 // explicitly marked comptime and rely on previous parameter comptime values, we
7360 // don't find out until after generating a monomorphed function whether the parameter
7361 // type ended up being a "must-be-comptime-known" type.
7362 var hasher = std.hash.Wyhash.init(0);
7363 std.hash.autoHash(&hasher, module_fn.owner_decl);
7364
7365 const generic_args = try sema.arena.alloc(GenericCallAdapter.Arg, func_ty_info.param_types.len);
7366 {
7367 var i: usize = 0;
7416 const monomorphed_args = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(generic_func_ty).?.param_types.len);
7417 const callee_index = callee: {
7418 var arg_i: usize = 0;
7419 var monomorphed_arg_i: u32 = 0;
7420 var known_unique = false;
73687421 for (fn_info.param_body) |inst| {
7422 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
73697423 var is_comptime = false;
73707424 var is_anytype = false;
73717425 switch (zir_tags[inst]) {
73727426 .param => {
7373 is_comptime = func_ty_info.paramIsComptime(i);
7427 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
73747428 },
73757429 .param_comptime => {
73767430 is_comptime = true;
73777431 },
73787432 .param_anytype => {
73797433 is_anytype = true;
7380 is_comptime = func_ty_info.paramIsComptime(i);
7434 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
73817435 },
73827436 .param_anytype_comptime => {
73837437 is_anytype = true;
......@@ -7386,87 +7440,90 @@ fn instantiateGenericCall(
73867440 else => continue,
73877441 }
73887442
7389 const arg_ty = sema.typeOf(uncasted_args[i]);
7443 defer arg_i += 1;
7444 const param_ty = generic_func_ty_info.param_types[arg_i];
7445 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7446
7447 if (known_unique) {
7448 if (is_comptime or is_anytype or is_generic) {
7449 monomorphed_arg_i += 1;
7450 }
7451 continue;
7452 }
7453
7454 const uncasted_arg = uncasted_args[arg_i];
7455 const arg_ty = if (is_generic) mod.monomorphed_funcs.getAdapted(
7456 Module.MonomorphedFuncAdaptedKey{
7457 .func = module_fn_index,
7458 .args = monomorphed_args[0..monomorphed_arg_i],
7459 },
7460 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7461 ) orelse {
7462 known_unique = true;
7463 monomorphed_arg_i += 1;
7464 continue;
7465 } else if (is_anytype) sema.typeOf(uncasted_arg).toIntern() else param_ty;
7466 const was_comptime = is_comptime;
7467 if (!is_comptime and try sema.typeRequiresComptime(arg_ty.toType())) is_comptime = true;
73907468 if (is_comptime or is_anytype) {
73917469 // Tuple default values are a part of the type and need to be
73927470 // resolved to hash the type.
7393 try sema.resolveTupleLazyValues(block, call_src, arg_ty);
7471 try sema.resolveTupleLazyValues(block, call_src, arg_ty.toType());
73947472 }
73957473
73967474 if (is_comptime) {
7397 const arg_val = sema.analyzeGenericCallArgVal(block, .unneeded, uncasted_args[i]) catch |err| switch (err) {
7475 const casted_arg = sema.analyzeGenericCallArgVal(block, .unneeded, arg_ty.toType(), uncasted_arg, "") catch |err| switch (err) {
73987476 error.NeededSourceLocation => {
7399 const decl = sema.mod.declPtr(block.src_decl);
7400 const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, i, bound_arg_src);
7401 _ = try sema.analyzeGenericCallArgVal(block, arg_src, uncasted_args[i]);
7477 const decl = mod.declPtr(block.src_decl);
7478 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
7479 _ = try sema.analyzeGenericCallArgVal(
7480 block,
7481 arg_src,
7482 arg_ty.toType(),
7483 uncasted_arg,
7484 if (was_comptime)
7485 "parameter is comptime"
7486 else
7487 "argument to parameter with comptime-only type must be comptime-known",
7488 );
74027489 unreachable;
74037490 },
74047491 else => |e| return e,
74057492 };
7406 arg_val.hashUncoerced(arg_ty, &hasher, mod);
7407 if (is_anytype) {
7408 arg_ty.hashWithHasher(&hasher, mod);
7409 generic_args[i] = .{
7410 .ty = arg_ty,
7411 .val = arg_val,
7412 .is_anytype = true,
7413 };
7414 } else {
7415 generic_args[i] = .{
7416 .ty = arg_ty,
7417 .val = arg_val,
7418 .is_anytype = false,
7419 };
7420 }
7421 } else if (is_anytype) {
7422 arg_ty.hashWithHasher(&hasher, mod);
7423 generic_args[i] = .{
7424 .ty = arg_ty,
7425 .val = Value.initTag(.generic_poison),
7426 .is_anytype = true,
7427 };
7428 } else {
7429 generic_args[i] = .{
7430 .ty = arg_ty,
7431 .val = Value.initTag(.generic_poison),
7432 .is_anytype = false,
7433 };
7493 monomorphed_args[monomorphed_arg_i] = casted_arg.toIntern();
7494 monomorphed_arg_i += 1;
7495 } else if (is_anytype or is_generic) {
7496 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty });
7497 monomorphed_arg_i += 1;
74347498 }
7435
7436 i += 1;
74377499 }
7438 }
74397500
7440 const precomputed_hash = hasher.final();
7501 if (!known_unique) {
7502 if (mod.monomorphed_funcs.getAdapted(
7503 Module.MonomorphedFuncAdaptedKey{
7504 .func = module_fn_index,
7505 .args = monomorphed_args[0..monomorphed_arg_i],
7506 },
7507 Module.MonomorphedFuncsAdaptedContext{ .mod = mod },
7508 )) |callee_func| break :callee mod.intern_pool.indexToKey(callee_func).func.index;
7509 }
74417510
7442 const adapter: GenericCallAdapter = .{
7443 .generic_fn = module_fn,
7444 .precomputed_hash = precomputed_hash,
7445 .func_ty_info = func_ty_info,
7446 .args = generic_args,
7447 .module = mod,
7448 };
7449 const gop = try mod.monomorphed_funcs.getOrPutAdapted(gpa, {}, adapter);
7450 const callee = if (!gop.found_existing) callee: {
7451 const new_module_func = try gpa.create(Module.Fn);
7511 const new_module_func_index = try mod.createFunc(undefined);
7512 const new_module_func = mod.funcPtr(new_module_func_index);
74527513
7453 // This ensures that we can operate on the hash map before the Module.Fn
7454 // struct is fully initialized.
7455 new_module_func.hash = precomputed_hash;
74567514 new_module_func.generic_owner_decl = module_fn.owner_decl.toOptional();
74577515 new_module_func.comptime_args = null;
7458 gop.key_ptr.* = new_module_func;
74597516
74607517 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
74617518
74627519 // Create a Decl for the new function.
7463 const src_decl_index = namespace.getDeclIndex();
7520 const src_decl_index = namespace.getDeclIndex(mod);
74647521 const src_decl = mod.declPtr(src_decl_index);
7465 const new_decl_index = try mod.allocateNewDecl(namespace, fn_owner_decl.src_node, src_decl.src_scope);
7522 const new_decl_index = try mod.allocateNewDecl(namespace_index, fn_owner_decl.src_node, src_decl.src_scope);
74667523 const new_decl = mod.declPtr(new_decl_index);
74677524 // TODO better names for generic function instantiations
7468 const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{
7469 fn_owner_decl.name, @enumToInt(new_decl_index),
7525 const decl_name = try mod.intern_pool.getOrPutStringFmt(gpa, "{}__anon_{d}", .{
7526 fn_owner_decl.name.fmt(&mod.intern_pool), @enumToInt(new_decl_index),
74707527 });
74717528 new_decl.name = decl_name;
74727529 new_decl.src_line = fn_owner_decl.src_line;
......@@ -7488,25 +7545,21 @@ fn instantiateGenericCall(
74887545 assert(new_decl.dependencies.keys().len == 0);
74897546 try mod.declareDeclDependencyType(new_decl_index, module_fn.owner_decl, .function_body);
74907547
7491 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
7492 const new_decl_arena_allocator = new_decl_arena.allocator();
7493
74947548 const new_func = sema.resolveGenericInstantiationType(
74957549 block,
7496 new_decl_arena_allocator,
74977550 fn_zir,
74987551 new_decl,
74997552 new_decl_index,
75007553 uncasted_args,
7501 module_fn,
7502 new_module_func,
7503 namespace,
7504 func_ty_info,
7554 monomorphed_arg_i,
7555 module_fn_index,
7556 new_module_func_index,
7557 namespace_index,
7558 generic_func_ty,
75057559 call_src,
75067560 bound_arg_src,
75077561 ) catch |err| switch (err) {
75087562 error.GenericPoison, error.ComptimeReturn => {
7509 new_decl_arena.deinit();
75107563 // Resolving the new function type below will possibly declare more decl dependencies
75117564 // and so we remove them all here in case of error.
75127565 for (new_decl.dependencies.keys()) |dep_index| {
......@@ -7515,16 +7568,10 @@ fn instantiateGenericCall(
75157568 }
75167569 assert(namespace.anon_decls.orderedRemove(new_decl_index));
75177570 mod.destroyDecl(new_decl_index);
7518 assert(mod.monomorphed_funcs.remove(new_module_func));
7519 gpa.destroy(new_module_func);
7571 mod.destroyFunc(new_module_func_index);
75207572 return err;
75217573 },
75227574 else => {
7523 assert(mod.monomorphed_funcs.remove(new_module_func));
7524 {
7525 errdefer new_decl_arena.deinit();
7526 try new_decl.finalizeNewArena(&new_decl_arena);
7527 }
75287575 // TODO look up the compile error that happened here and attach a note to it
75297576 // pointing here, at the generic instantiation callsite.
75307577 if (sema.owner_func) |owner_func| {
......@@ -7535,12 +7582,10 @@ fn instantiateGenericCall(
75357582 return err;
75367583 },
75377584 };
7538 errdefer new_decl_arena.deinit();
75397585
7540 try new_decl.finalizeNewArena(&new_decl_arena);
75417586 break :callee new_func;
7542 } else gop.key_ptr.*;
7543
7587 };
7588 const callee = mod.funcPtr(callee_index);
75447589 callee.branch_quota = @max(callee.branch_quota, sema.branch_quota);
75457590
75467591 const callee_inst = try sema.analyzeDeclVal(block, func_src, callee.owner_decl);
......@@ -7548,8 +7593,7 @@ fn instantiateGenericCall(
75487593 // Make a runtime call to the new function, making sure to omit the comptime args.
75497594 const comptime_args = callee.comptime_args.?;
75507595 const func_ty = mod.declPtr(callee.owner_decl).ty;
7551 const new_fn_info = func_ty.fnInfo();
7552 const runtime_args_len = @intCast(u32, new_fn_info.param_types.len);
7596 const runtime_args_len = @intCast(u32, mod.typeToFunc(func_ty).?.param_types.len);
75537597 const runtime_args = try sema.arena.alloc(Air.Inst.Ref, runtime_args_len);
75547598 {
75557599 var runtime_i: u32 = 0;
......@@ -7565,18 +7609,18 @@ fn instantiateGenericCall(
75657609 uncasted_args[total_i],
75667610 comptime_args[total_i],
75677611 runtime_args,
7568 new_fn_info,
7612 mod.typeToFunc(func_ty).?,
75697613 &runtime_i,
75707614 ) catch |err| switch (err) {
75717615 error.NeededSourceLocation => {
7572 const decl = sema.mod.declPtr(block.src_decl);
7616 const decl = mod.declPtr(block.src_decl);
75737617 _ = try sema.analyzeGenericCallArg(
75747618 block,
7575 Module.argSrc(call_src.node_offset.x, sema.gpa, decl, total_i, bound_arg_src),
7619 mod.argSrc(call_src.node_offset.x, decl, total_i, bound_arg_src),
75767620 uncasted_args[total_i],
75777621 comptime_args[total_i],
75787622 runtime_args,
7579 new_fn_info,
7623 mod.typeToFunc(func_ty).?,
75807624 &runtime_i,
75817625 );
75827626 unreachable;
......@@ -7586,16 +7630,16 @@ fn instantiateGenericCall(
75867630 total_i += 1;
75877631 }
75887632
7589 try sema.queueFullTypeResolution(new_fn_info.return_type);
7633 try sema.queueFullTypeResolution(mod.typeToFunc(func_ty).?.return_type.toType());
75907634 }
75917635
75927636 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some);
75937637
7594 if (sema.owner_func != null and new_fn_info.return_type.isError()) {
7638 if (sema.owner_func != null and mod.typeToFunc(func_ty).?.return_type.toType().isError(mod)) {
75957639 sema.owner_func.?.calls_or_awaits_errorable_fn = true;
75967640 }
75977641
7598 try sema.mod.ensureFuncBodyAnalysisQueued(callee);
7642 try mod.ensureFuncBodyAnalysisQueued(callee_index);
75997643
76007644 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Call).Struct.fields.len +
76017645 runtime_args_len);
......@@ -7616,7 +7660,7 @@ fn instantiateGenericCall(
76167660 if (call_tag == .call_always_tail) {
76177661 return sema.handleTailCall(block, call_src, func_ty, result);
76187662 }
7619 if (new_fn_info.return_type.isNoReturn()) {
7663 if (func_ty.fnReturnType(mod).isNoReturn(mod)) {
76207664 _ = try block.addNoOp(.unreach);
76217665 return Air.Inst.Ref.unreachable_value;
76227666 }
......@@ -7626,22 +7670,23 @@ fn instantiateGenericCall(
76267670fn resolveGenericInstantiationType(
76277671 sema: *Sema,
76287672 block: *Block,
7629 new_decl_arena_allocator: Allocator,
76307673 fn_zir: Zir,
76317674 new_decl: *Decl,
76327675 new_decl_index: Decl.Index,
76337676 uncasted_args: []const Air.Inst.Ref,
7634 module_fn: *Module.Fn,
7635 new_module_func: *Module.Fn,
7636 namespace: *Namespace,
7637 func_ty_info: Type.Payload.Function.Data,
7677 monomorphed_args_len: u32,
7678 module_fn_index: Module.Fn.Index,
7679 new_module_func: Module.Fn.Index,
7680 namespace: Namespace.Index,
7681 generic_func_ty: Type,
76387682 call_src: LazySrcLoc,
76397683 bound_arg_src: ?LazySrcLoc,
7640) !*Module.Fn {
7684) !Module.Fn.Index {
76417685 const mod = sema.mod;
76427686 const gpa = sema.gpa;
76437687
76447688 const zir_tags = fn_zir.instructions.items(.tag);
7689 const module_fn = mod.funcPtr(module_fn_index);
76457690 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
76467691
76477692 // Re-run the block that creates the function, with the comptime parameters
......@@ -7652,23 +7697,26 @@ fn resolveGenericInstantiationType(
76527697 .mod = mod,
76537698 .gpa = gpa,
76547699 .arena = sema.arena,
7655 .perm_arena = new_decl_arena_allocator,
76567700 .code = fn_zir,
76577701 .owner_decl = new_decl,
76587702 .owner_decl_index = new_decl_index,
76597703 .func = null,
7704 .func_index = .none,
76607705 .fn_ret_ty = Type.void,
76617706 .owner_func = null,
7662 .comptime_args = try new_decl_arena_allocator.alloc(TypedValue, uncasted_args.len),
7707 .owner_func_index = .none,
7708 // TODO: fully migrate functions into InternPool
7709 .comptime_args = try mod.tmp_hack_arena.allocator().alloc(TypedValue, uncasted_args.len),
76637710 .comptime_args_fn_inst = module_fn.zir_body_inst,
7664 .preallocated_new_func = new_module_func,
7711 .preallocated_new_func = new_module_func.toOptional(),
76657712 .is_generic_instantiation = true,
76667713 .branch_quota = sema.branch_quota,
76677714 .branch_count = sema.branch_count,
7715 .comptime_mutable_decls = sema.comptime_mutable_decls,
76687716 };
76697717 defer child_sema.deinit();
76707718
7671 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope);
7719 var wip_captures = try WipCaptureScope.init(gpa, new_decl.src_scope);
76727720 defer wip_captures.deinit();
76737721
76747722 var child_block: Block = .{
......@@ -7690,18 +7738,19 @@ fn resolveGenericInstantiationType(
76907738
76917739 var arg_i: usize = 0;
76927740 for (fn_info.param_body) |inst| {
7741 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
76937742 var is_comptime = false;
76947743 var is_anytype = false;
76957744 switch (zir_tags[inst]) {
76967745 .param => {
7697 is_comptime = func_ty_info.paramIsComptime(arg_i);
7746 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
76987747 },
76997748 .param_comptime => {
77007749 is_comptime = true;
77017750 },
77027751 .param_anytype => {
77037752 is_anytype = true;
7704 is_comptime = func_ty_info.paramIsComptime(arg_i);
7753 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77057754 },
77067755 .param_anytype_comptime => {
77077756 is_anytype = true;
......@@ -7719,8 +7768,8 @@ fn resolveGenericInstantiationType(
77197768 if (try sema.typeRequiresComptime(arg_ty)) {
77207769 const arg_val = sema.resolveConstValue(block, .unneeded, arg, "") catch |err| switch (err) {
77217770 error.NeededSourceLocation => {
7722 const decl = sema.mod.declPtr(block.src_decl);
7723 const arg_src = Module.argSrc(call_src.node_offset.x, sema.gpa, decl, arg_i, bound_arg_src);
7771 const decl = mod.declPtr(block.src_decl);
7772 const arg_src = mod.argSrc(call_src.node_offset.x, decl, arg_i, bound_arg_src);
77247773 _ = try sema.resolveConstValue(block, arg_src, arg, "argument to parameter with comptime-only type must be comptime-known");
77257774 unreachable;
77267775 },
......@@ -7752,50 +7801,61 @@ fn resolveGenericInstantiationType(
77527801
77537802 const new_func_inst = try child_sema.resolveBody(&child_block, fn_info.param_body, fn_info.param_body_inst);
77547803 const new_func_val = child_sema.resolveConstValue(&child_block, .unneeded, new_func_inst, undefined) catch unreachable;
7755 const new_func = new_func_val.castTag(.function).?.data;
7756 errdefer new_func.deinit(gpa);
7804 const new_func = new_func_val.getFunctionIndex(mod).unwrap().?;
77577805 assert(new_func == new_module_func);
77587806
7807 const monomorphed_args_index = @intCast(u32, mod.monomorphed_func_keys.items.len);
7808 const monomorphed_args = try mod.monomorphed_func_keys.addManyAsSlice(gpa, monomorphed_args_len);
7809 var monomorphed_arg_i: u32 = 0;
7810 try mod.monomorphed_funcs.ensureUnusedCapacityContext(gpa, monomorphed_args_len + 1, .{ .mod = mod });
7811
77597812 arg_i = 0;
77607813 for (fn_info.param_body) |inst| {
7814 const generic_func_ty_info = mod.typeToFunc(generic_func_ty).?;
77617815 var is_comptime = false;
7816 var is_anytype = false;
77627817 switch (zir_tags[inst]) {
77637818 .param => {
7764 is_comptime = func_ty_info.paramIsComptime(arg_i);
7819 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77657820 },
77667821 .param_comptime => {
77677822 is_comptime = true;
77687823 },
77697824 .param_anytype => {
7770 is_comptime = func_ty_info.paramIsComptime(arg_i);
7825 is_anytype = true;
7826 is_comptime = generic_func_ty_info.paramIsComptime(@intCast(u5, arg_i));
77717827 },
77727828 .param_anytype_comptime => {
7829 is_anytype = true;
77737830 is_comptime = true;
77747831 },
77757832 else => continue,
77767833 }
77777834
7778 // We populate the Type here regardless because it is needed by
7779 // `GenericCallAdapter.eql` as well as function body analysis.
7780 // Whether it is anytype is communicated by `isAnytypeParam`.
7835 const param_ty = generic_func_ty_info.param_types[arg_i];
7836 const is_generic = !is_anytype and param_ty == .generic_poison_type;
7837
77817838 const arg = child_sema.inst_map.get(inst).?;
7782 const copied_arg_ty = try child_sema.typeOf(arg).copy(new_decl_arena_allocator);
7839 const arg_ty = child_sema.typeOf(arg);
77837840
7784 if (try sema.typeRequiresComptime(copied_arg_ty)) {
7785 is_comptime = true;
7786 }
7841 if (is_generic) if (mod.monomorphed_funcs.fetchPutAssumeCapacityContext(.{
7842 .func = module_fn_index,
7843 .args_index = monomorphed_args_index,
7844 .args_len = monomorphed_arg_i,
7845 }, arg_ty.toIntern(), .{ .mod = mod })) |kv| assert(kv.value == arg_ty.toIntern());
7846 if (!is_comptime and try sema.typeRequiresComptime(arg_ty)) is_comptime = true;
77877847
77887848 if (is_comptime) {
77897849 const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?;
7790 child_sema.comptime_args[arg_i] = .{
7791 .ty = copied_arg_ty,
7792 .val = try arg_val.copy(new_decl_arena_allocator),
7793 };
7850 monomorphed_args[monomorphed_arg_i] = arg_val.toIntern();
7851 monomorphed_arg_i += 1;
7852 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = arg_val };
77947853 } else {
7795 child_sema.comptime_args[arg_i] = .{
7796 .ty = copied_arg_ty,
7797 .val = Value.initTag(.generic_poison),
7798 };
7854 if (is_anytype or is_generic) {
7855 monomorphed_args[monomorphed_arg_i] = try mod.intern(.{ .undef = arg_ty.toIntern() });
7856 monomorphed_arg_i += 1;
7857 }
7858 child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, .val = Value.generic_poison };
77997859 }
78007860
78017861 arg_i += 1;
......@@ -7804,11 +7864,11 @@ fn resolveGenericInstantiationType(
78047864 try wip_captures.finalize();
78057865
78067866 // Populate the Decl ty/val with the function and its type.
7807 new_decl.ty = try child_sema.typeOf(new_func_inst).copy(new_decl_arena_allocator);
7867 new_decl.ty = child_sema.typeOf(new_func_inst);
78087868 // If the call evaluated to a return type that requires comptime, never mind
78097869 // our generic instantiation. Instead we need to perform a comptime call.
7810 const new_fn_info = new_decl.ty.fnInfo();
7811 if (try sema.typeRequiresComptime(new_fn_info.return_type)) {
7870 const new_fn_info = mod.typeToFunc(new_decl.ty).?;
7871 if (try sema.typeRequiresComptime(new_fn_info.return_type.toType())) {
78127872 return error.ComptimeReturn;
78137873 }
78147874 // Similarly, if the call evaluated to a generic type we need to instead
......@@ -7817,15 +7877,20 @@ fn resolveGenericInstantiationType(
78177877 return error.GenericPoison;
78187878 }
78197879
7820 new_decl.val = try Value.Tag.function.create(new_decl_arena_allocator, new_func);
7880 new_decl.val = (try mod.intern(.{ .func = .{
7881 .ty = new_decl.ty.toIntern(),
7882 .index = new_func,
7883 } })).toValue();
78217884 new_decl.@"align" = 0;
78227885 new_decl.has_tv = true;
78237886 new_decl.owns_tv = true;
78247887 new_decl.analysis = .complete;
78257888
7826 log.debug("generic function '{s}' instantiated with type {}", .{
7827 new_decl.name, new_decl.ty.fmtDebug(),
7828 });
7889 mod.monomorphed_funcs.putAssumeCapacityNoClobberContext(.{
7890 .func = module_fn_index,
7891 .args_index = monomorphed_args_index,
7892 .args_len = monomorphed_arg_i,
7893 }, new_decl.val.toIntern(), .{ .mod = mod });
78297894
78307895 // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field
78317896 // will be populated, ensuring it will have `analyzeBody` called with the ZIR
......@@ -7835,46 +7900,46 @@ fn resolveGenericInstantiationType(
78357900}
78367901
78377902fn resolveTupleLazyValues(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
7838 if (!ty.isSimpleTupleOrAnonStruct()) return;
7839 const tuple = ty.tupleFields();
7840 for (tuple.values, 0..) |field_val, i| {
7841 try sema.resolveTupleLazyValues(block, src, tuple.types[i]);
7842 if (field_val.tag() == .unreachable_value) continue;
7843 try sema.resolveLazyValue(field_val);
7903 const mod = sema.mod;
7904 const tuple = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
7905 .anon_struct_type => |tuple| tuple,
7906 else => return,
7907 };
7908 for (tuple.types, tuple.values) |field_ty, field_val| {
7909 try sema.resolveTupleLazyValues(block, src, field_ty.toType());
7910 if (field_val == .none) continue;
7911 // TODO: mutate in intern pool
7912 _ = try sema.resolveLazyValue(field_val.toValue());
78447913 }
78457914}
78467915
78477916fn emitDbgInline(
78487917 sema: *Sema,
78497918 block: *Block,
7850 old_func: *Module.Fn,
7851 new_func: *Module.Fn,
7919 old_func: Module.Fn.Index,
7920 new_func: Module.Fn.Index,
78527921 new_func_ty: Type,
78537922 tag: Air.Inst.Tag,
78547923) CompileError!void {
7855 if (sema.mod.comp.bin_file.options.strip) return;
7924 const mod = sema.mod;
7925 if (mod.comp.bin_file.options.strip) return;
78567926
78577927 // Recursive inline call; no dbg_inline needed.
78587928 if (old_func == new_func) return;
78597929
7860 try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
78617930 _ = try block.addInst(.{
78627931 .tag = tag,
7863 .data = .{ .ty_pl = .{
7932 .data = .{ .ty_fn = .{
78647933 .ty = try sema.addType(new_func_ty),
7865 .payload = @intCast(u32, sema.air_values.items.len - 1),
7934 .func = new_func,
78667935 } },
78677936 });
78687937}
78697938
7870fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7871 _ = block;
7872 const tracy = trace(@src());
7873 defer tracy.end();
7874
7939fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7940 const mod = sema.mod;
78757941 const int_type = sema.code.instructions.items(.data)[inst].int_type;
7876 const ty = try Module.makeIntType(sema.arena, int_type.signedness, int_type.bit_count);
7877
7942 const ty = try mod.intType(int_type.signedness, int_type.bit_count);
78787943 return sema.addType(ty);
78797944}
78807945
......@@ -7882,43 +7947,46 @@ fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
78827947 const tracy = trace(@src());
78837948 defer tracy.end();
78847949
7950 const mod = sema.mod;
78857951 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
78867952 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };
78877953 const child_type = try sema.resolveType(block, operand_src, inst_data.operand);
7888 if (child_type.zigTypeTag() == .Opaque) {
7889 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(sema.mod)});
7890 } else if (child_type.zigTypeTag() == .Null) {
7891 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(sema.mod)});
7954 if (child_type.zigTypeTag(mod) == .Opaque) {
7955 return sema.fail(block, operand_src, "opaque type '{}' cannot be optional", .{child_type.fmt(mod)});
7956 } else if (child_type.zigTypeTag(mod) == .Null) {
7957 return sema.fail(block, operand_src, "type '{}' cannot be optional", .{child_type.fmt(mod)});
78927958 }
7893 const opt_type = try Type.optional(sema.arena, child_type);
7959 const opt_type = try Type.optional(sema.arena, child_type, mod);
78947960
78957961 return sema.addType(opt_type);
78967962}
78977963
78987964fn zirElemTypeIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7965 const mod = sema.mod;
78997966 const bin = sema.code.instructions.items(.data)[inst].bin;
79007967 const indexable_ty = try sema.resolveType(block, .unneeded, bin.lhs);
7901 assert(indexable_ty.isIndexable()); // validated by a previous instruction
7902 if (indexable_ty.zigTypeTag() == .Struct) {
7903 const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs));
7968 assert(indexable_ty.isIndexable(mod)); // validated by a previous instruction
7969 if (indexable_ty.zigTypeTag(mod) == .Struct) {
7970 const elem_type = indexable_ty.structFieldType(@enumToInt(bin.rhs), mod);
79047971 return sema.addType(elem_type);
79057972 } else {
7906 const elem_type = indexable_ty.elemType2();
7973 const elem_type = indexable_ty.elemType2(mod);
79077974 return sema.addType(elem_type);
79087975 }
79097976}
79107977
79117978fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
7979 const mod = sema.mod;
79127980 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
79137981 const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
79147982 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
79157983 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
7916 const len = try sema.resolveInt(block, len_src, extra.lhs, Type.u32, "vector length must be comptime-known");
7984 const len = @intCast(u32, try sema.resolveInt(block, len_src, extra.lhs, Type.u32, "vector length must be comptime-known"));
79177985 const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs);
79187986 try sema.checkVectorElemType(block, elem_type_src, elem_type);
7919 const vector_type = try Type.Tag.vector.create(sema.arena, .{
7920 .len = @intCast(u32, len),
7921 .elem_type = elem_type,
7987 const vector_type = try mod.vectorType(.{
7988 .len = len,
7989 .child = elem_type.toIntern(),
79227990 });
79237991 return sema.addType(vector_type);
79247992}
......@@ -7960,9 +8028,10 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
79608028}
79618029
79628030fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: LazySrcLoc) !void {
7963 if (elem_type.zigTypeTag() == .Opaque) {
7964 return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(sema.mod)});
7965 } else if (elem_type.zigTypeTag() == .NoReturn) {
8031 const mod = sema.mod;
8032 if (elem_type.zigTypeTag(mod) == .Opaque) {
8033 return sema.fail(block, elem_src, "array of opaque type '{}' not allowed", .{elem_type.fmt(mod)});
8034 } else if (elem_type.zigTypeTag(mod) == .NoReturn) {
79668035 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{});
79678036 }
79688037}
......@@ -7975,9 +8044,10 @@ fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
79758044 if (true) {
79768045 return sema.failWithUseOfAsync(block, inst_data.src());
79778046 }
8047 const mod = sema.mod;
79788048 const operand_src: LazySrcLoc = .{ .node_offset_anyframe_type = inst_data.src_node };
79798049 const return_type = try sema.resolveType(block, operand_src, inst_data.operand);
7980 const anyframe_type = try Type.Tag.anyframe_T.create(sema.arena, return_type);
8050 const anyframe_type = try mod.anyframeType(return_type);
79818051
79828052 return sema.addType(anyframe_type);
79838053}
......@@ -7986,6 +8056,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
79868056 const tracy = trace(@src());
79878057 defer tracy.end();
79888058
8059 const mod = sema.mod;
79898060 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
79908061 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
79918062 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
......@@ -7993,50 +8064,48 @@ fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
79938064 const error_set = try sema.resolveType(block, lhs_src, extra.lhs);
79948065 const payload = try sema.resolveType(block, rhs_src, extra.rhs);
79958066
7996 if (error_set.zigTypeTag() != .ErrorSet) {
8067 if (error_set.zigTypeTag(mod) != .ErrorSet) {
79978068 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{
7998 error_set.fmt(sema.mod),
8069 error_set.fmt(mod),
79998070 });
80008071 }
80018072 try sema.validateErrorUnionPayloadType(block, payload, rhs_src);
8002 const err_union_ty = try Type.errorUnion(sema.arena, error_set, payload, sema.mod);
8073 const err_union_ty = try mod.errorUnionType(error_set, payload);
80038074 return sema.addType(err_union_ty);
80048075}
80058076
80068077fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, payload_src: LazySrcLoc) !void {
8007 if (payload_ty.zigTypeTag() == .Opaque) {
8078 const mod = sema.mod;
8079 if (payload_ty.zigTypeTag(mod) == .Opaque) {
80088080 return sema.fail(block, payload_src, "error union with payload of opaque type '{}' not allowed", .{
8009 payload_ty.fmt(sema.mod),
8081 payload_ty.fmt(mod),
80108082 });
8011 } else if (payload_ty.zigTypeTag() == .ErrorSet) {
8083 } else if (payload_ty.zigTypeTag(mod) == .ErrorSet) {
80128084 return sema.fail(block, payload_src, "error union with payload of error set type '{}' not allowed", .{
8013 payload_ty.fmt(sema.mod),
8085 payload_ty.fmt(mod),
80148086 });
80158087 }
80168088}
80178089
80188090fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
80198091 _ = block;
8020 const tracy = trace(@src());
8021 defer tracy.end();
8022
8092 const mod = sema.mod;
80238093 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
8024
8025 // Create an anonymous error set type with only this error value, and return the value.
8026 const kv = try sema.mod.getErrorValue(inst_data.get(sema.code));
8027 const result_type = try Type.Tag.error_set_single.create(sema.arena, kv.key);
8028 return sema.addConstant(
8029 result_type,
8030 try Value.Tag.@"error".create(sema.arena, .{
8031 .name = kv.key,
8032 }),
8033 );
8094 const name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
8095 _ = try mod.getErrorValue(name);
8096 // Create an error set type with only this error value, and return the value.
8097 const error_set_type = try mod.singleErrorSetType(name);
8098 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
8099 .ty = error_set_type.toIntern(),
8100 .name = name,
8101 } })).toValue());
80348102}
80358103
80368104fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
80378105 const tracy = trace(@src());
80388106 defer tracy.end();
80398107
8108 const mod = sema.mod;
80408109 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
80418110 const src = LazySrcLoc.nodeOffset(extra.node);
80428111 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -8044,34 +8113,26 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
80448113 const operand = try sema.coerce(block, Type.anyerror, uncasted_operand, operand_src);
80458114
80468115 if (try sema.resolveMaybeUndefVal(operand)) |val| {
8047 if (val.isUndef()) {
8116 if (val.isUndef(mod)) {
80488117 return sema.addConstUndef(Type.err_int);
80498118 }
8050 switch (val.tag()) {
8051 .@"error" => {
8052 const payload = try sema.arena.create(Value.Payload.U64);
8053 payload.* = .{
8054 .base = .{ .tag = .int_u64 },
8055 .data = (try sema.mod.getErrorValue(val.castTag(.@"error").?.data.name)).value,
8056 };
8057 return sema.addConstant(Type.err_int, Value.initPayload(&payload.base));
8058 },
8059
8060 // This is not a valid combination with the type `anyerror`.
8061 .the_only_possible_value => unreachable,
8062
8063 // Assume it's already encoded as an integer.
8064 else => return sema.addConstant(Type.err_int, val),
8065 }
8119 const err_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
8120 return sema.addConstant(Type.err_int, try mod.intValue(
8121 Type.err_int,
8122 try mod.getErrorValue(err_name),
8123 ));
80668124 }
80678125
80688126 const op_ty = sema.typeOf(uncasted_operand);
80698127 try sema.resolveInferredErrorSetTy(block, src, op_ty);
8070 if (!op_ty.isAnyError()) {
8071 const names = op_ty.errorSetNames();
8128 if (!op_ty.isAnyError(mod)) {
8129 const names = op_ty.errorSetNames(mod);
80728130 switch (names.len) {
8073 0 => return sema.addConstant(Type.err_int, Value.zero),
8074 1 => return sema.addIntUnsigned(Type.err_int, sema.mod.global_error_set.get(names[0]).?),
8131 0 => return sema.addConstant(Type.err_int, try mod.intValue(Type.err_int, 0)),
8132 1 => {
8133 const int = @intCast(Module.ErrorInt, mod.global_error_set.getIndex(names[0]).?);
8134 return sema.addIntUnsigned(Type.err_int, int);
8135 },
80758136 else => {},
80768137 }
80778138 }
......@@ -8084,28 +8145,26 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
80848145 const tracy = trace(@src());
80858146 defer tracy.end();
80868147
8148 const mod = sema.mod;
80878149 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
80888150 const src = LazySrcLoc.nodeOffset(extra.node);
80898151 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
80908152 const uncasted_operand = try sema.resolveInst(extra.operand);
80918153 const operand = try sema.coerce(block, Type.err_int, uncasted_operand, operand_src);
8092 const target = sema.mod.getTarget();
80938154
80948155 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
8095 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(target));
8096 if (int > sema.mod.global_error_set.count() or int == 0)
8156 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(mod));
8157 if (int > mod.global_error_set.count() or int == 0)
80978158 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
8098 const payload = try sema.arena.create(Value.Payload.Error);
8099 payload.* = .{
8100 .base = .{ .tag = .@"error" },
8101 .data = .{ .name = sema.mod.error_name_list.items[int] },
8102 };
8103 return sema.addConstant(Type.anyerror, Value.initPayload(&payload.base));
8159 return sema.addConstant(Type.anyerror, (try mod.intern(.{ .err = .{
8160 .ty = .anyerror_type,
8161 .name = mod.global_error_set.keys()[int],
8162 } })).toValue());
81048163 }
81058164 try sema.requireRuntimeBlock(block, src, operand_src);
81068165 if (block.wantSafety()) {
81078166 const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);
8108 const zero_val = try sema.addConstant(Type.err_int, Value.zero);
8167 const zero_val = try sema.addConstant(Type.err_int, try mod.intValue(Type.err_int, 0));
81098168 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
81108169 const ok = try block.addBinOp(.bit_and, is_lt_len, is_non_zero);
81118170 try sema.addSafetyCheck(block, ok, .invalid_error_code);
......@@ -8123,6 +8182,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
81238182 const tracy = trace(@src());
81248183 defer tracy.end();
81258184
8185 const mod = sema.mod;
81268186 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
81278187 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
81288188 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
......@@ -8130,7 +8190,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
81308190 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
81318191 const lhs = try sema.resolveInst(extra.lhs);
81328192 const rhs = try sema.resolveInst(extra.rhs);
8133 if (sema.typeOf(lhs).zigTypeTag() == .Bool and sema.typeOf(rhs).zigTypeTag() == .Bool) {
8193 if (sema.typeOf(lhs).zigTypeTag(mod) == .Bool and sema.typeOf(rhs).zigTypeTag(mod) == .Bool) {
81348194 const msg = msg: {
81358195 const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{});
81368196 errdefer msg.destroy(sema.gpa);
......@@ -8141,32 +8201,32 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
81418201 }
81428202 const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs);
81438203 const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs);
8144 if (lhs_ty.zigTypeTag() != .ErrorSet)
8145 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(sema.mod)});
8146 if (rhs_ty.zigTypeTag() != .ErrorSet)
8147 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(sema.mod)});
8204 if (lhs_ty.zigTypeTag(mod) != .ErrorSet)
8205 return sema.fail(block, lhs_src, "expected error set type, found '{}'", .{lhs_ty.fmt(mod)});
8206 if (rhs_ty.zigTypeTag(mod) != .ErrorSet)
8207 return sema.fail(block, rhs_src, "expected error set type, found '{}'", .{rhs_ty.fmt(mod)});
81488208
81498209 // Anything merged with anyerror is anyerror.
8150 if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) {
8210 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) {
81518211 return Air.Inst.Ref.anyerror_type;
81528212 }
81538213
8154 if (lhs_ty.castTag(.error_set_inferred)) |payload| {
8155 try sema.resolveInferredErrorSet(block, src, payload.data);
8214 if (mod.typeToInferredErrorSetIndex(lhs_ty).unwrap()) |ies_index| {
8215 try sema.resolveInferredErrorSet(block, src, ies_index);
81568216 // isAnyError might have changed from a false negative to a true positive after resolution.
8157 if (lhs_ty.isAnyError()) {
8217 if (lhs_ty.isAnyError(mod)) {
81588218 return Air.Inst.Ref.anyerror_type;
81598219 }
81608220 }
8161 if (rhs_ty.castTag(.error_set_inferred)) |payload| {
8162 try sema.resolveInferredErrorSet(block, src, payload.data);
8221 if (mod.typeToInferredErrorSetIndex(rhs_ty).unwrap()) |ies_index| {
8222 try sema.resolveInferredErrorSet(block, src, ies_index);
81638223 // isAnyError might have changed from a false negative to a true positive after resolution.
8164 if (rhs_ty.isAnyError()) {
8224 if (rhs_ty.isAnyError(mod)) {
81658225 return Air.Inst.Ref.anyerror_type;
81668226 }
81678227 }
81688228
8169 const err_set_ty = try lhs_ty.errorSetMerge(sema.arena, rhs_ty);
8229 const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty);
81708230 return sema.addType(err_set_ty);
81718231}
81728232
......@@ -8175,27 +8235,27 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
81758235 const tracy = trace(@src());
81768236 defer tracy.end();
81778237
8238 const mod = sema.mod;
81788239 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
8179 const duped_name = try sema.arena.dupe(u8, inst_data.get(sema.code));
8180 return sema.addConstant(
8181 Type.initTag(.enum_literal),
8182 try Value.Tag.enum_literal.create(sema.arena, duped_name),
8183 );
8240 const name = inst_data.get(sema.code);
8241 return sema.addConstant(.{ .ip_index = .enum_literal_type }, (try mod.intern(.{
8242 .enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name),
8243 })).toValue());
81848244}
81858245
81868246fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8187 const arena = sema.arena;
8247 const mod = sema.mod;
81888248 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
81898249 const src = inst_data.src();
81908250 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
81918251 const operand = try sema.resolveInst(inst_data.operand);
81928252 const operand_ty = sema.typeOf(operand);
81938253
8194 const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag()) {
8254 const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(mod)) {
81958255 .Enum => operand,
81968256 .Union => blk: {
81978257 const union_ty = try sema.resolveTypeFields(operand_ty);
8198 const tag_ty = union_ty.unionTagType() orelse {
8258 const tag_ty = union_ty.unionTagType(mod) orelse {
81998259 return sema.fail(
82008260 block,
82018261 operand_src,
......@@ -8207,22 +8267,20 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82078267 },
82088268 else => {
82098269 return sema.fail(block, operand_src, "expected enum or tagged union, found '{}'", .{
8210 operand_ty.fmt(sema.mod),
8270 operand_ty.fmt(mod),
82118271 });
82128272 },
82138273 };
82148274 const enum_tag_ty = sema.typeOf(enum_tag);
82158275
8216 var int_tag_type_buffer: Type.Payload.Bits = undefined;
8217 const int_tag_ty = try enum_tag_ty.intTagType(&int_tag_type_buffer).copy(arena);
8276 const int_tag_ty = enum_tag_ty.intTagType(mod);
82188277
82198278 if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| {
8220 return sema.addConstant(int_tag_ty, opv);
8279 return sema.addConstant(int_tag_ty, try mod.getCoerced(opv, int_tag_ty));
82218280 }
82228281
82238282 if (try sema.resolveMaybeUndefVal(enum_tag)) |enum_tag_val| {
8224 var buffer: Value.Payload.U64 = undefined;
8225 const val = enum_tag_val.enumToInt(enum_tag_ty, &buffer);
8283 const val = try enum_tag_val.enumToInt(enum_tag_ty, mod);
82268284 return sema.addConstant(int_tag_ty, try val.copy(sema.arena));
82278285 }
82288286
......@@ -8231,6 +8289,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82318289}
82328290
82338291fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
8292 const mod = sema.mod;
82348293 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
82358294 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
82368295 const src = inst_data.src();
......@@ -8239,24 +8298,23 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82398298 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
82408299 const operand = try sema.resolveInst(extra.rhs);
82418300
8242 if (dest_ty.zigTypeTag() != .Enum) {
8243 return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(sema.mod)});
8301 if (dest_ty.zigTypeTag(mod) != .Enum) {
8302 return sema.fail(block, dest_ty_src, "expected enum, found '{}'", .{dest_ty.fmt(mod)});
82448303 }
82458304 _ = try sema.checkIntType(block, operand_src, sema.typeOf(operand));
82468305
82478306 if (try sema.resolveMaybeUndefVal(operand)) |int_val| {
8248 if (dest_ty.isNonexhaustiveEnum()) {
8249 var buffer: Type.Payload.Bits = undefined;
8250 const int_tag_ty = dest_ty.intTagType(&buffer);
8307 if (dest_ty.isNonexhaustiveEnum(mod)) {
8308 const int_tag_ty = dest_ty.intTagType(mod);
82518309 if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
8252 return sema.addConstant(dest_ty, int_val);
8310 return sema.addConstant(dest_ty, try mod.getCoerced(int_val, dest_ty));
82538311 }
82548312 const msg = msg: {
82558313 const msg = try sema.errMsg(
82568314 block,
82578315 src,
82588316 "int value '{}' out of range of non-exhaustive enum '{}'",
8259 .{ int_val.fmtValue(sema.typeOf(operand), sema.mod), dest_ty.fmt(sema.mod) },
8317 .{ int_val.fmtValue(sema.typeOf(operand), mod), dest_ty.fmt(mod) },
82608318 );
82618319 errdefer msg.destroy(sema.gpa);
82628320 try sema.addDeclaredHereNote(msg, dest_ty);
......@@ -8264,7 +8322,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82648322 };
82658323 return sema.failWithOwnedErrorMsg(msg);
82668324 }
8267 if (int_val.isUndef()) {
8325 if (int_val.isUndef(mod)) {
82688326 return sema.failWithUseOfUndef(block, operand_src);
82698327 }
82708328 if (!(try sema.enumHasInt(dest_ty, int_val))) {
......@@ -8273,7 +8331,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82738331 block,
82748332 src,
82758333 "enum '{}' has no tag with value '{}'",
8276 .{ dest_ty.fmt(sema.mod), int_val.fmtValue(sema.typeOf(operand), sema.mod) },
8334 .{ dest_ty.fmt(mod), int_val.fmtValue(sema.typeOf(operand), mod) },
82778335 );
82788336 errdefer msg.destroy(sema.gpa);
82798337 try sema.addDeclaredHereNote(msg, dest_ty);
......@@ -8281,7 +8339,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82818339 };
82828340 return sema.failWithOwnedErrorMsg(msg);
82838341 }
8284 return sema.addConstant(dest_ty, int_val);
8342 return sema.addConstant(dest_ty, try mod.getCoerced(int_val, dest_ty));
82858343 }
82868344
82878345 if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| {
......@@ -8295,8 +8353,8 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
82958353
82968354 try sema.requireRuntimeBlock(block, src, operand_src);
82978355 const result = try block.addTyOp(.intcast, dest_ty, operand);
8298 if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum() and
8299 sema.mod.backendSupportsFeature(.is_named_enum_value))
8356 if (block.wantSafety() and !dest_ty.isNonexhaustiveEnum(mod) and
8357 mod.backendSupportsFeature(.is_named_enum_value))
83008358 {
83018359 const ok = try block.addUnOp(.is_named_enum_value, result);
83028360 try sema.addSafetyCheck(block, ok, .invalid_enum_value);
......@@ -8329,49 +8387,44 @@ fn analyzeOptionalPayloadPtr(
83298387 safety_check: bool,
83308388 initializing: bool,
83318389) CompileError!Air.Inst.Ref {
8390 const mod = sema.mod;
83328391 const optional_ptr_ty = sema.typeOf(optional_ptr);
8333 assert(optional_ptr_ty.zigTypeTag() == .Pointer);
8392 assert(optional_ptr_ty.zigTypeTag(mod) == .Pointer);
83348393
8335 const opt_type = optional_ptr_ty.elemType();
8336 if (opt_type.zigTypeTag() != .Optional) {
8337 return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(sema.mod)});
8394 const opt_type = optional_ptr_ty.childType(mod);
8395 if (opt_type.zigTypeTag(mod) != .Optional) {
8396 return sema.fail(block, src, "expected optional type, found '{}'", .{opt_type.fmt(mod)});
83388397 }
83398398
8340 const child_type = try opt_type.optionalChildAlloc(sema.arena);
8341 const child_pointer = try Type.ptr(sema.arena, sema.mod, .{
8399 const child_type = opt_type.optionalChild(mod);
8400 const child_pointer = try Type.ptr(sema.arena, mod, .{
83428401 .pointee_type = child_type,
8343 .mutable = !optional_ptr_ty.isConstPtr(),
8344 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(),
8402 .mutable = !optional_ptr_ty.isConstPtr(mod),
8403 .@"addrspace" = optional_ptr_ty.ptrAddressSpace(mod),
83458404 });
83468405
83478406 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| {
83488407 if (initializing) {
8349 if (!ptr_val.isComptimeMutablePtr()) {
8408 if (!ptr_val.isComptimeMutablePtr(mod)) {
83508409 // If the pointer resulting from this function was stored at comptime,
83518410 // the optional non-null bit would be set that way. But in this case,
83528411 // we need to emit a runtime instruction to do it.
83538412 _ = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr);
83548413 }
8355 return sema.addConstant(
8356 child_pointer,
8357 try Value.Tag.opt_payload_ptr.create(sema.arena, .{
8358 .container_ptr = ptr_val,
8359 .container_ty = optional_ptr_ty.childType(),
8360 }),
8361 );
8414 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8415 .ty = child_pointer.toIntern(),
8416 .addr = .{ .opt_payload = ptr_val.toIntern() },
8417 } })).toValue());
83628418 }
83638419 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| {
8364 if (val.isNull()) {
8420 if (val.isNull(mod)) {
83658421 return sema.fail(block, src, "unable to unwrap null", .{});
83668422 }
83678423 // The same Value represents the pointer to the optional and the payload.
8368 return sema.addConstant(
8369 child_pointer,
8370 try Value.Tag.opt_payload_ptr.create(sema.arena, .{
8371 .container_ptr = ptr_val,
8372 .container_ty = optional_ptr_ty.childType(),
8373 }),
8374 );
8424 return sema.addConstant(child_pointer, (try mod.intern(.{ .ptr = .{
8425 .ty = child_pointer.toIntern(),
8426 .addr = .{ .opt_payload = ptr_val.toIntern() },
8427 } })).toValue());
83758428 }
83768429 }
83778430
......@@ -8397,21 +8450,22 @@ fn zirOptionalPayload(
83978450 const tracy = trace(@src());
83988451 defer tracy.end();
83998452
8453 const mod = sema.mod;
84008454 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
84018455 const src = inst_data.src();
84028456 const operand = try sema.resolveInst(inst_data.operand);
84038457 const operand_ty = sema.typeOf(operand);
8404 const result_ty = switch (operand_ty.zigTypeTag()) {
8405 .Optional => try operand_ty.optionalChildAlloc(sema.arena),
8458 const result_ty = switch (operand_ty.zigTypeTag(mod)) {
8459 .Optional => operand_ty.optionalChild(mod),
84068460 .Pointer => t: {
8407 if (operand_ty.ptrSize() != .C) {
8461 if (operand_ty.ptrSize(mod) != .C) {
84088462 return sema.failWithExpectedOptionalType(block, src, operand_ty);
84098463 }
84108464 // TODO https://github.com/ziglang/zig/issues/6597
84118465 if (true) break :t operand_ty;
8412 const ptr_info = operand_ty.ptrInfo().data;
8413 break :t try Type.ptr(sema.arena, sema.mod, .{
8414 .pointee_type = try ptr_info.pointee_type.copy(sema.arena),
8466 const ptr_info = operand_ty.ptrInfo(mod);
8467 break :t try Type.ptr(sema.arena, mod, .{
8468 .pointee_type = ptr_info.pointee_type,
84158469 .@"align" = ptr_info.@"align",
84168470 .@"addrspace" = ptr_info.@"addrspace",
84178471 .mutable = ptr_info.mutable,
......@@ -8424,13 +8478,10 @@ fn zirOptionalPayload(
84248478 };
84258479
84268480 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8427 if (val.isNull()) {
8428 return sema.fail(block, src, "unable to unwrap null", .{});
8429 }
8430 if (val.castTag(.opt_payload)) |payload| {
8431 return sema.addConstant(result_ty, payload.data);
8432 }
8433 return sema.addConstant(result_ty, val);
8481 return if (val.optionalValue(mod)) |payload|
8482 sema.addConstant(result_ty, payload)
8483 else
8484 sema.fail(block, src, "unable to unwrap null", .{});
84348485 }
84358486
84368487 try sema.requireRuntimeBlock(block, src, null);
......@@ -8450,14 +8501,15 @@ fn zirErrUnionPayload(
84508501 const tracy = trace(@src());
84518502 defer tracy.end();
84528503
8504 const mod = sema.mod;
84538505 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
84548506 const src = inst_data.src();
84558507 const operand = try sema.resolveInst(inst_data.operand);
84568508 const operand_src = src;
84578509 const err_union_ty = sema.typeOf(operand);
8458 if (err_union_ty.zigTypeTag() != .ErrorUnion) {
8510 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) {
84598511 return sema.fail(block, operand_src, "expected error union type, found '{}'", .{
8460 err_union_ty.fmt(sema.mod),
8512 err_union_ty.fmt(mod),
84618513 });
84628514 }
84638515 return sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false);
......@@ -8468,24 +8520,27 @@ fn analyzeErrUnionPayload(
84688520 block: *Block,
84698521 src: LazySrcLoc,
84708522 err_union_ty: Type,
8471 operand: Zir.Inst.Ref,
8523 operand: Air.Inst.Ref,
84728524 operand_src: LazySrcLoc,
84738525 safety_check: bool,
84748526) CompileError!Air.Inst.Ref {
8475 const payload_ty = err_union_ty.errorUnionPayload();
8527 const mod = sema.mod;
8528 const payload_ty = err_union_ty.errorUnionPayload(mod);
84768529 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
8477 if (val.getError()) |name| {
8478 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
8530 if (val.getErrorName(mod).unwrap()) |name| {
8531 return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)});
84798532 }
8480 const data = val.castTag(.eu_payload).?.data;
8481 return sema.addConstant(payload_ty, data);
8533 return sema.addConstant(
8534 payload_ty,
8535 mod.intern_pool.indexToKey(val.toIntern()).error_union.val.payload.toValue(),
8536 );
84828537 }
84838538
84848539 try sema.requireRuntimeBlock(block, src, null);
84858540
84868541 // If the error set has no fields then no safety check is needed.
84878542 if (safety_check and block.wantSafety() and
8488 !err_union_ty.errorUnionSet().errorSetIsEmpty())
8543 !err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod))
84898544 {
84908545 try sema.panicUnwrapError(block, operand, .unwrap_errunion_err, .is_non_err);
84918546 }
......@@ -8517,52 +8572,46 @@ fn analyzeErrUnionPayloadPtr(
85178572 safety_check: bool,
85188573 initializing: bool,
85198574) CompileError!Air.Inst.Ref {
8575 const mod = sema.mod;
85208576 const operand_ty = sema.typeOf(operand);
8521 assert(operand_ty.zigTypeTag() == .Pointer);
8577 assert(operand_ty.zigTypeTag(mod) == .Pointer);
85228578
8523 if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) {
8579 if (operand_ty.childType(mod).zigTypeTag(mod) != .ErrorUnion) {
85248580 return sema.fail(block, src, "expected error union type, found '{}'", .{
8525 operand_ty.elemType().fmt(sema.mod),
8581 operand_ty.childType(mod).fmt(mod),
85268582 });
85278583 }
85288584
8529 const err_union_ty = operand_ty.elemType();
8530 const payload_ty = err_union_ty.errorUnionPayload();
8531 const operand_pointer_ty = try Type.ptr(sema.arena, sema.mod, .{
8585 const err_union_ty = operand_ty.childType(mod);
8586 const payload_ty = err_union_ty.errorUnionPayload(mod);
8587 const operand_pointer_ty = try Type.ptr(sema.arena, mod, .{
85328588 .pointee_type = payload_ty,
8533 .mutable = !operand_ty.isConstPtr(),
8534 .@"addrspace" = operand_ty.ptrAddressSpace(),
8589 .mutable = !operand_ty.isConstPtr(mod),
8590 .@"addrspace" = operand_ty.ptrAddressSpace(mod),
85358591 });
85368592
85378593 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| {
85388594 if (initializing) {
8539 if (!ptr_val.isComptimeMutablePtr()) {
8595 if (!ptr_val.isComptimeMutablePtr(mod)) {
85408596 // If the pointer resulting from this function was stored at comptime,
85418597 // the error union error code would be set that way. But in this case,
85428598 // we need to emit a runtime instruction to do it.
85438599 try sema.requireRuntimeBlock(block, src, null);
85448600 _ = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand);
85458601 }
8546 return sema.addConstant(
8547 operand_pointer_ty,
8548 try Value.Tag.eu_payload_ptr.create(sema.arena, .{
8549 .container_ptr = ptr_val,
8550 .container_ty = operand_ty.elemType(),
8551 }),
8552 );
8602 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8603 .ty = operand_pointer_ty.toIntern(),
8604 .addr = .{ .eu_payload = ptr_val.toIntern() },
8605 } })).toValue());
85538606 }
85548607 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| {
8555 if (val.getError()) |name| {
8556 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
8608 if (val.getErrorName(mod).unwrap()) |name| {
8609 return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&mod.intern_pool)});
85578610 }
8558
8559 return sema.addConstant(
8560 operand_pointer_ty,
8561 try Value.Tag.eu_payload_ptr.create(sema.arena, .{
8562 .container_ptr = ptr_val,
8563 .container_ty = operand_ty.elemType(),
8564 }),
8565 );
8611 return sema.addConstant(operand_pointer_ty, (try mod.intern(.{ .ptr = .{
8612 .ty = operand_pointer_ty.toIntern(),
8613 .addr = .{ .eu_payload = ptr_val.toIntern() },
8614 } })).toValue());
85668615 }
85678616 }
85688617
......@@ -8570,7 +8619,7 @@ fn analyzeErrUnionPayloadPtr(
85708619
85718620 // If the error set has no fields then no safety check is needed.
85728621 if (safety_check and block.wantSafety() and
8573 !err_union_ty.errorUnionSet().errorSetIsEmpty())
8622 !err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod))
85748623 {
85758624 try sema.panicUnwrapError(block, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr);
85768625 }
......@@ -8594,18 +8643,21 @@ fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
85948643}
85958644
85968645fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref {
8646 const mod = sema.mod;
85978647 const operand_ty = sema.typeOf(operand);
8598 if (operand_ty.zigTypeTag() != .ErrorUnion) {
8648 if (operand_ty.zigTypeTag(mod) != .ErrorUnion) {
85998649 return sema.fail(block, src, "expected error union type, found '{}'", .{
8600 operand_ty.fmt(sema.mod),
8650 operand_ty.fmt(mod),
86018651 });
86028652 }
86038653
8604 const result_ty = operand_ty.errorUnionSet();
8654 const result_ty = operand_ty.errorUnionSet(mod);
86058655
86068656 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
8607 assert(val.getError() != null);
8608 return sema.addConstant(result_ty, val);
8657 return sema.addConstant(result_ty, (try mod.intern(.{ .err = .{
8658 .ty = result_ty.toIntern(),
8659 .name = mod.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name,
8660 } })).toValue());
86098661 }
86108662
86118663 try sema.requireRuntimeBlock(block, src, null);
......@@ -8617,23 +8669,24 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
86178669 const tracy = trace(@src());
86188670 defer tracy.end();
86198671
8672 const mod = sema.mod;
86208673 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
86218674 const src = inst_data.src();
86228675 const operand = try sema.resolveInst(inst_data.operand);
86238676 const operand_ty = sema.typeOf(operand);
8624 assert(operand_ty.zigTypeTag() == .Pointer);
8677 assert(operand_ty.zigTypeTag(mod) == .Pointer);
86258678
8626 if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) {
8679 if (operand_ty.childType(mod).zigTypeTag(mod) != .ErrorUnion) {
86278680 return sema.fail(block, src, "expected error union type, found '{}'", .{
8628 operand_ty.elemType().fmt(sema.mod),
8681 operand_ty.childType(mod).fmt(mod),
86298682 });
86308683 }
86318684
8632 const result_ty = operand_ty.elemType().errorUnionSet();
8685 const result_ty = operand_ty.childType(mod).errorUnionSet(mod);
86338686
86348687 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| {
86358688 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| {
8636 assert(val.getError() != null);
8689 assert(val.getErrorName(mod) != .none);
86378690 return sema.addConstant(result_ty, val);
86388691 }
86398692 }
......@@ -8667,7 +8720,7 @@ fn zirFunc(
86678720 break :blk ret_ty;
86688721 } else |err| switch (err) {
86698722 error.GenericPoison => {
8670 break :blk Type.initTag(.generic_poison);
8723 break :blk Type.generic_poison;
86718724 },
86728725 else => |e| return e,
86738726 }
......@@ -8677,8 +8730,7 @@ fn zirFunc(
86778730 extra_index += ret_ty_body.len;
86788731
86798732 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, Type.type, "return type must be comptime-known");
8680 var buffer: Value.ToTypeBuffer = undefined;
8681 break :blk try ret_ty_val.toType(&buffer).copy(sema.arena);
8733 break :blk ret_ty_val.toType();
86828734 },
86838735 };
86848736
......@@ -8745,10 +8797,10 @@ fn resolveGenericBody(
87458797 };
87468798 switch (err) {
87478799 error.GenericPoison => {
8748 if (dest_ty.tag() == .type) {
8749 return Value.initTag(.generic_poison_type);
8800 if (dest_ty.toIntern() == .type_type) {
8801 return Value.generic_poison_type;
87508802 } else {
8751 return Value.initTag(.generic_poison);
8803 return Value.generic_poison;
87528804 }
87538805 },
87548806 else => |e| return e,
......@@ -8822,7 +8874,7 @@ fn handleExternLibName(
88228874const FuncLinkSection = union(enum) {
88238875 generic,
88248876 default,
8825 explicit: []const u8,
8877 explicit: InternPool.NullTerminatedString,
88268878};
88278879
88288880fn funcCommon(
......@@ -8849,11 +8901,13 @@ fn funcCommon(
88498901 noalias_bits: u32,
88508902 is_noinline: bool,
88518903) CompileError!Air.Inst.Ref {
8904 const mod = sema.mod;
8905 const gpa = sema.gpa;
88528906 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
88538907 const cc_src: LazySrcLoc = .{ .node_offset_fn_type_cc = src_node_offset };
88548908 const func_src = LazySrcLoc.nodeOffset(src_node_offset);
88558909
8856 var is_generic = bare_return_type.tag() == .generic_poison or
8910 var is_generic = bare_return_type.isGenericPoison() or
88578911 alignment == null or
88588912 address_space == null or
88598913 section == .generic or
......@@ -8869,70 +8923,42 @@ fn funcCommon(
88698923 }
88708924
88718925 var destroy_fn_on_error = false;
8872 const new_func: *Module.Fn = new_func: {
8926 const new_func_index = new_func: {
88738927 if (!has_body) break :new_func undefined;
88748928 if (sema.comptime_args_fn_inst == func_inst) {
8875 const new_func = sema.preallocated_new_func.?;
8876 sema.preallocated_new_func = null; // take ownership
8877 break :new_func new_func;
8929 const new_func_index = sema.preallocated_new_func.unwrap().?;
8930 sema.preallocated_new_func = .none; // take ownership
8931 break :new_func new_func_index;
88788932 }
88798933 destroy_fn_on_error = true;
8880 const new_func = try sema.gpa.create(Module.Fn);
8934 var new_func: Module.Fn = undefined;
88818935 // Set this here so that the inferred return type can be printed correctly if it appears in an error.
88828936 new_func.owner_decl = sema.owner_decl_index;
8883 break :new_func new_func;
8937 const new_func_index = try mod.createFunc(new_func);
8938 break :new_func new_func_index;
88848939 };
8885 errdefer if (destroy_fn_on_error) sema.gpa.destroy(new_func);
8886
8887 var maybe_inferred_error_set_node: ?*Module.Fn.InferredErrorSetListNode = null;
8888 errdefer if (maybe_inferred_error_set_node) |node| sema.gpa.destroy(node);
8889 // Note: no need to errdefer since this will still be in its default state at the end of the function.
8940 errdefer if (destroy_fn_on_error) mod.destroyFunc(new_func_index);
88908941
8891 const target = sema.mod.getTarget();
8942 const target = mod.getTarget();
88928943 const fn_ty: Type = fn_ty: {
8893 // Hot path for some common function types.
8894 // TODO can we eliminate some of these Type tag values? seems unnecessarily complicated.
8895 if (!is_generic and block.params.items.len == 0 and !var_args and !inferred_error_set and
8896 alignment.? == 0 and
8897 address_space.? == target_util.defaultAddressSpace(target, .function) and
8898 section == .default and
8899 !is_noinline)
8900 {
8901 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Unspecified) {
8902 break :fn_ty Type.initTag(.fn_noreturn_no_args);
8903 }
8904
8905 if (bare_return_type.zigTypeTag() == .Void and cc.? == .Unspecified) {
8906 break :fn_ty Type.initTag(.fn_void_no_args);
8907 }
8908
8909 if (bare_return_type.zigTypeTag() == .NoReturn and cc.? == .Naked) {
8910 break :fn_ty Type.initTag(.fn_naked_noreturn_no_args);
8911 }
8912
8913 if (bare_return_type.zigTypeTag() == .Void and cc.? == .C) {
8914 break :fn_ty Type.initTag(.fn_ccc_void_no_args);
8915 }
8916 }
8917
89188944 // In the case of generic calling convention, or generic alignment, we use
89198945 // default values which are only meaningful for the generic function, *not*
89208946 // the instantiation, which can depend on comptime parameters.
89218947 // Related proposal: https://github.com/ziglang/zig/issues/11834
89228948 const cc_resolved = cc orelse .Unspecified;
8923 const param_types = try sema.arena.alloc(Type, block.params.items.len);
8924 const comptime_params = try sema.arena.alloc(bool, block.params.items.len);
8925 for (block.params.items, 0..) |param, i| {
8949 const param_types = try sema.arena.alloc(InternPool.Index, block.params.items.len);
8950 var comptime_bits: u32 = 0;
8951 for (param_types, block.params.items, 0..) |*dest_param_ty, param, i| {
89268952 const is_noalias = blk: {
89278953 const index = std.math.cast(u5, i) orelse break :blk false;
89288954 break :blk @truncate(u1, noalias_bits >> index) != 0;
89298955 };
8930 param_types[i] = param.ty;
8956 dest_param_ty.* = param.ty.toIntern();
89318957 sema.analyzeParameter(
89328958 block,
89338959 .unneeded,
89348960 param,
8935 comptime_params,
8961 &comptime_bits,
89368962 i,
89378963 &is_generic,
89388964 cc_resolved,
......@@ -8940,12 +8966,12 @@ fn funcCommon(
89408966 is_noalias,
89418967 ) catch |err| switch (err) {
89428968 error.NeededSourceLocation => {
8943 const decl = sema.mod.declPtr(block.src_decl);
8969 const decl = mod.declPtr(block.src_decl);
89448970 try sema.analyzeParameter(
89458971 block,
8946 Module.paramSrc(src_node_offset, sema.gpa, decl, i),
8972 Module.paramSrc(src_node_offset, mod, decl, i),
89478973 param,
8948 comptime_params,
8974 &comptime_bits,
89498975 i,
89508976 &is_generic,
89518977 cc_resolved,
......@@ -8961,7 +8987,7 @@ fn funcCommon(
89618987 var ret_ty_requires_comptime = false;
89628988 const ret_poison = if (sema.typeRequiresComptime(bare_return_type)) |ret_comptime| rp: {
89638989 ret_ty_requires_comptime = ret_comptime;
8964 break :rp bare_return_type.tag() == .generic_poison;
8990 break :rp bare_return_type.isGenericPoison();
89658991 } else |err| switch (err) {
89668992 error.GenericPoison => rp: {
89678993 is_generic = true;
......@@ -8970,43 +8996,41 @@ fn funcCommon(
89708996 else => |e| return e,
89718997 };
89728998
8973 const return_type = if (!inferred_error_set or ret_poison)
8999 const return_type: Type = if (!inferred_error_set or ret_poison)
89749000 bare_return_type
89759001 else blk: {
89769002 try sema.validateErrorUnionPayloadType(block, bare_return_type, ret_ty_src);
8977 const node = try sema.gpa.create(Module.Fn.InferredErrorSetListNode);
8978 node.data = .{ .func = new_func };
8979 maybe_inferred_error_set_node = node;
8980
8981 const error_set_ty = try Type.Tag.error_set_inferred.create(sema.arena, &node.data);
8982 break :blk try Type.Tag.error_union.create(sema.arena, .{
8983 .error_set = error_set_ty,
8984 .payload = bare_return_type,
9003 const ies_index = try mod.intern_pool.createInferredErrorSet(gpa, .{
9004 .func = new_func_index,
89859005 });
9006 const error_set_ty = try mod.intern(.{ .inferred_error_set_type = ies_index });
9007 break :blk try mod.errorUnionType(error_set_ty.toType(), bare_return_type);
89869008 };
89879009
8988 if (!return_type.isValidReturnType()) {
8989 const opaque_str = if (return_type.zigTypeTag() == .Opaque) "opaque " else "";
9010 if (!return_type.isValidReturnType(mod)) {
9011 const opaque_str = if (return_type.zigTypeTag(mod) == .Opaque) "opaque " else "";
89909012 const msg = msg: {
89919013 const msg = try sema.errMsg(block, ret_ty_src, "{s}return type '{}' not allowed", .{
8992 opaque_str, return_type.fmt(sema.mod),
9014 opaque_str, return_type.fmt(mod),
89939015 });
8994 errdefer msg.destroy(sema.gpa);
9016 errdefer msg.destroy(gpa);
89959017
89969018 try sema.addDeclaredHereNote(msg, return_type);
89979019 break :msg msg;
89989020 };
89999021 return sema.failWithOwnedErrorMsg(msg);
90009022 }
9001 if (!ret_poison and !Type.fnCallingConventionAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(return_type, .ret_ty)) {
9023 if (!ret_poison and !target_util.fnCallConvAllowsZigTypes(target, cc_resolved) and
9024 !try sema.validateExternType(return_type, .ret_ty))
9025 {
90029026 const msg = msg: {
90039027 const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{
9004 return_type.fmt(sema.mod), @tagName(cc_resolved),
9028 return_type.fmt(mod), @tagName(cc_resolved),
90059029 });
9006 errdefer msg.destroy(sema.gpa);
9030 errdefer msg.destroy(gpa);
90079031
9008 const src_decl = sema.mod.declPtr(block.src_decl);
9009 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl), return_type, .ret_ty);
9032 const src_decl = mod.declPtr(block.src_decl);
9033 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src.toSrcLoc(src_decl, mod), return_type, .ret_ty);
90109034
90119035 try sema.addDeclaredHereNote(msg, return_type);
90129036 break :msg msg;
......@@ -9024,9 +9048,9 @@ fn funcCommon(
90249048 block,
90259049 ret_ty_src,
90269050 "function with comptime-only return type '{}' requires all parameters to be comptime",
9027 .{return_type.fmt(sema.mod)},
9051 .{return_type.fmt(mod)},
90289052 );
9029 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl), return_type);
9053 try sema.explainWhyTypeIsComptime(msg, ret_ty_src.toSrcLoc(sema.owner_decl, mod), return_type);
90309054
90319055 const tags = sema.code.instructions.items(.tag);
90329056 const data = sema.code.instructions.items(.data);
......@@ -9049,7 +9073,7 @@ fn funcCommon(
90499073 return sema.failWithOwnedErrorMsg(msg);
90509074 }
90519075
9052 const arch = sema.mod.getTarget().cpu.arch;
9076 const arch = mod.getTarget().cpu.arch;
90539077 if (switch (cc_resolved) {
90549078 .Unspecified, .C, .Naked, .Async, .Inline => null,
90559079 .Interrupt => switch (arch) {
......@@ -9092,8 +9116,7 @@ fn funcCommon(
90929116 return sema.fail(block, cc_src, "'noinline' function cannot have callconv 'Inline'", .{});
90939117 }
90949118 if (is_generic and sema.no_partial_func_ty) return error.GenericPoison;
9095 for (comptime_params) |ct| is_generic = is_generic or ct;
9096 is_generic = is_generic or ret_ty_requires_comptime;
9119 is_generic = is_generic or comptime_bits != 0 or ret_ty_requires_comptime;
90979120
90989121 if (!is_generic and sema.wantErrorReturnTracing(return_type)) {
90999122 // Make sure that StackTrace's fields are resolved so that the backend can
......@@ -9102,68 +9125,58 @@ fn funcCommon(
91029125 _ = try sema.resolveTypeFields(unresolved_stack_trace_ty);
91039126 }
91049127
9105 break :fn_ty try Type.Tag.function.create(sema.arena, .{
9128 break :fn_ty try mod.funcType(.{
91069129 .param_types = param_types,
9107 .comptime_params = comptime_params.ptr,
9108 .return_type = return_type,
9130 .noalias_bits = noalias_bits,
9131 .comptime_bits = comptime_bits,
9132 .return_type = return_type.toIntern(),
91099133 .cc = cc_resolved,
91109134 .cc_is_generic = cc == null,
9111 .alignment = alignment orelse 0,
9135 .alignment = if (alignment) |a| InternPool.Alignment.fromByteUnits(a) else .none,
91129136 .align_is_generic = alignment == null,
91139137 .section_is_generic = section == .generic,
91149138 .addrspace_is_generic = address_space == null,
91159139 .is_var_args = var_args,
91169140 .is_generic = is_generic,
91179141 .is_noinline = is_noinline,
9118 .noalias_bits = noalias_bits,
91199142 });
91209143 };
91219144
91229145 sema.owner_decl.@"linksection" = switch (section) {
9123 .generic => undefined,
9124 .default => null,
9125 .explicit => |section_name| try sema.perm_arena.dupeZ(u8, section_name),
9146 .generic => .none,
9147 .default => .none,
9148 .explicit => |section_name| section_name.toOptional(),
91269149 };
91279150 sema.owner_decl.@"align" = alignment orelse 0;
91289151 sema.owner_decl.@"addrspace" = address_space orelse .generic;
91299152
91309153 if (is_extern) {
9131 const new_extern_fn = try sema.gpa.create(Module.ExternFn);
9132 errdefer sema.gpa.destroy(new_extern_fn);
9133
9134 new_extern_fn.* = Module.ExternFn{
9135 .owner_decl = sema.owner_decl_index,
9136 .lib_name = null,
9137 };
9138
9139 if (opt_lib_name) |lib_name| {
9140 new_extern_fn.lib_name = try sema.handleExternLibName(block, .{
9141 .node_offset_lib_name = src_node_offset,
9142 }, lib_name);
9143 }
9144
9145 const extern_fn_payload = try sema.arena.create(Value.Payload.ExternFn);
9146 extern_fn_payload.* = .{
9147 .base = .{ .tag = .extern_fn },
9148 .data = new_extern_fn,
9149 };
9150 return sema.addConstant(fn_ty, Value.initPayload(&extern_fn_payload.base));
9154 return sema.addConstant(fn_ty, (try mod.intern(.{ .extern_func = .{
9155 .ty = fn_ty.toIntern(),
9156 .decl = sema.owner_decl_index,
9157 .lib_name = if (opt_lib_name) |lib_name| (try mod.intern_pool.getOrPutString(
9158 gpa,
9159 try sema.handleExternLibName(block, .{
9160 .node_offset_lib_name = src_node_offset,
9161 }, lib_name),
9162 )).toOptional() else .none,
9163 } })).toValue());
91519164 }
91529165
91539166 if (!has_body) {
91549167 return sema.addType(fn_ty);
91559168 }
91569169
9157 const is_inline = fn_ty.fnCallingConvention() == .Inline;
9170 const is_inline = fn_ty.fnCallingConvention(mod) == .Inline;
91589171 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .none;
91599172
91609173 const comptime_args: ?[*]TypedValue = if (sema.comptime_args_fn_inst == func_inst) blk: {
91619174 break :blk if (sema.comptime_args.len == 0) null else sema.comptime_args.ptr;
91629175 } else null;
91639176
9177 const new_func = mod.funcPtr(new_func_index);
91649178 const hash = new_func.hash;
91659179 const generic_owner_decl = if (comptime_args == null) .none else new_func.generic_owner_decl;
9166 const fn_payload = try sema.arena.create(Value.Payload.Function);
91679180 new_func.* = .{
91689181 .state = anal_state,
91699182 .zir_body_inst = func_inst,
......@@ -9178,15 +9191,10 @@ fn funcCommon(
91789191 .branch_quota = default_branch_quota,
91799192 .is_noinline = is_noinline,
91809193 };
9181 if (maybe_inferred_error_set_node) |node| {
9182 new_func.inferred_error_sets.prepend(node);
9183 }
9184 maybe_inferred_error_set_node = null;
9185 fn_payload.* = .{
9186 .base = .{ .tag = .function },
9187 .data = new_func,
9188 };
9189 return sema.addConstant(fn_ty, Value.initPayload(&fn_payload.base));
9194 return sema.addConstant(fn_ty, (try mod.intern(.{ .func = .{
9195 .ty = fn_ty.toIntern(),
9196 .index = new_func_index,
9197 } })).toValue());
91909198}
91919199
91929200fn analyzeParameter(
......@@ -9194,29 +9202,32 @@ fn analyzeParameter(
91949202 block: *Block,
91959203 param_src: LazySrcLoc,
91969204 param: Block.Param,
9197 comptime_params: []bool,
9205 comptime_bits: *u32,
91989206 i: usize,
91999207 is_generic: *bool,
92009208 cc: std.builtin.CallingConvention,
92019209 has_body: bool,
92029210 is_noalias: bool,
92039211) !void {
9212 const mod = sema.mod;
92049213 const requires_comptime = try sema.typeRequiresComptime(param.ty);
9205 comptime_params[i] = param.is_comptime or requires_comptime;
9206 const this_generic = param.ty.tag() == .generic_poison;
9214 if (param.is_comptime or requires_comptime) {
9215 comptime_bits.* |= @as(u32, 1) << @intCast(u5, i); // TODO: handle cast error
9216 }
9217 const this_generic = param.ty.isGenericPoison();
92079218 is_generic.* = is_generic.* or this_generic;
9208 const target = sema.mod.getTarget();
9209 if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) {
9219 const target = mod.getTarget();
9220 if (param.is_comptime and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
92109221 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
92119222 }
9212 if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(target, cc)) {
9223 if (this_generic and !sema.no_partial_func_ty and !target_util.fnCallConvAllowsZigTypes(target, cc)) {
92139224 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)});
92149225 }
9215 if (!param.ty.isValidParamType()) {
9216 const opaque_str = if (param.ty.zigTypeTag() == .Opaque) "opaque " else "";
9226 if (!param.ty.isValidParamType(mod)) {
9227 const opaque_str = if (param.ty.zigTypeTag(mod) == .Opaque) "opaque " else "";
92179228 const msg = msg: {
92189229 const msg = try sema.errMsg(block, param_src, "parameter of {s}type '{}' not allowed", .{
9219 opaque_str, param.ty.fmt(sema.mod),
9230 opaque_str, param.ty.fmt(mod),
92209231 });
92219232 errdefer msg.destroy(sema.gpa);
92229233
......@@ -9225,15 +9236,15 @@ fn analyzeParameter(
92259236 };
92269237 return sema.failWithOwnedErrorMsg(msg);
92279238 }
9228 if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) {
9239 if (!this_generic and !target_util.fnCallConvAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) {
92299240 const msg = msg: {
92309241 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{
9231 param.ty.fmt(sema.mod), @tagName(cc),
9242 param.ty.fmt(mod), @tagName(cc),
92329243 });
92339244 errdefer msg.destroy(sema.gpa);
92349245
9235 const src_decl = sema.mod.declPtr(block.src_decl);
9236 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl), param.ty, .param_ty);
9246 const src_decl = mod.declPtr(block.src_decl);
9247 try sema.explainWhyTypeIsNotExtern(msg, param_src.toSrcLoc(src_decl, mod), param.ty, .param_ty);
92379248
92389249 try sema.addDeclaredHereNote(msg, param.ty);
92399250 break :msg msg;
......@@ -9243,12 +9254,12 @@ fn analyzeParameter(
92439254 if (!sema.is_generic_instantiation and requires_comptime and !param.is_comptime and has_body) {
92449255 const msg = msg: {
92459256 const msg = try sema.errMsg(block, param_src, "parameter of type '{}' must be declared comptime", .{
9246 param.ty.fmt(sema.mod),
9257 param.ty.fmt(mod),
92479258 });
92489259 errdefer msg.destroy(sema.gpa);
92499260
9250 const src_decl = sema.mod.declPtr(block.src_decl);
9251 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl), param.ty);
9261 const src_decl = mod.declPtr(block.src_decl);
9262 try sema.explainWhyTypeIsComptime(msg, param_src.toSrcLoc(src_decl, mod), param.ty);
92529263
92539264 try sema.addDeclaredHereNote(msg, param.ty);
92549265 break :msg msg;
......@@ -9256,7 +9267,7 @@ fn analyzeParameter(
92569267 return sema.failWithOwnedErrorMsg(msg);
92579268 }
92589269 if (!sema.is_generic_instantiation and !this_generic and is_noalias and
9259 !(param.ty.zigTypeTag() == .Pointer or param.ty.isPtrLikeOptional()))
9270 !(param.ty.zigTypeTag(mod) == .Pointer or param.ty.isPtrLikeOptional(mod)))
92609271 {
92619272 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{});
92629273 }
......@@ -9283,7 +9294,7 @@ fn zirParam(
92839294 const prev_preallocated_new_func = sema.preallocated_new_func;
92849295 const prev_no_partial_func_type = sema.no_partial_func_ty;
92859296 block.params = .{};
9286 sema.preallocated_new_func = null;
9297 sema.preallocated_new_func = .none;
92879298 sema.no_partial_func_ty = true;
92889299 defer {
92899300 block.params.deinit(sema.gpa);
......@@ -9309,7 +9320,7 @@ fn zirParam(
93099320 // We result the param instruction with a poison value and
93109321 // insert an anytype parameter.
93119322 try block.params.append(sema.gpa, .{
9312 .ty = Type.initTag(.generic_poison),
9323 .ty = Type.generic_poison,
93139324 .is_comptime = comptime_syntax,
93149325 .name = param_name,
93159326 });
......@@ -9330,7 +9341,7 @@ fn zirParam(
93309341 // We result the param instruction with a poison value and
93319342 // insert an anytype parameter.
93329343 try block.params.append(sema.gpa, .{
9333 .ty = Type.initTag(.generic_poison),
9344 .ty = Type.generic_poison,
93349345 .is_comptime = comptime_syntax,
93359346 .name = param_name,
93369347 });
......@@ -9340,7 +9351,7 @@ fn zirParam(
93409351 else => |e| return e,
93419352 } or comptime_syntax;
93429353 if (sema.inst_map.get(inst)) |arg| {
9343 if (is_comptime and sema.preallocated_new_func != null) {
9354 if (is_comptime and sema.preallocated_new_func != .none) {
93449355 // We have a comptime value for this parameter so it should be elided from the
93459356 // function type of the function instruction in this block.
93469357 const coerced_arg = sema.coerce(block, param_ty, arg, .unneeded) catch |err| switch (err) {
......@@ -9363,7 +9374,7 @@ fn zirParam(
93639374 assert(sema.inst_map.remove(inst));
93649375 }
93659376
9366 if (sema.preallocated_new_func != null) {
9377 if (sema.preallocated_new_func != .none) {
93679378 if (try sema.typeHasOnePossibleValue(param_ty)) |opv| {
93689379 // In this case we are instantiating a generic function call with a non-comptime
93699380 // non-anytype parameter that ended up being a one-possible-type.
......@@ -9383,7 +9394,7 @@ fn zirParam(
93839394 if (is_comptime) {
93849395 // If this is a comptime parameter we can add a constant generic_poison
93859396 // since this is also a generic parameter.
9386 const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison));
9397 const result = try sema.addConstant(Type.generic_poison, Value.generic_poison);
93879398 sema.inst_map.putAssumeCapacityNoClobber(inst, result);
93889399 } else {
93899400 // Otherwise we need a dummy runtime instruction.
......@@ -9428,7 +9439,7 @@ fn zirParamAnytype(
94289439 // We are evaluating a generic function without any comptime args provided.
94299440
94309441 try block.params.append(sema.gpa, .{
9431 .ty = Type.initTag(.generic_poison),
9442 .ty = Type.generic_poison,
94329443 .is_comptime = comptime_syntax,
94339444 .name = param_name,
94349445 });
......@@ -9472,13 +9483,14 @@ fn analyzeAs(
94729483 zir_operand: Zir.Inst.Ref,
94739484 no_cast_to_comptime_int: bool,
94749485) CompileError!Air.Inst.Ref {
9486 const mod = sema.mod;
94759487 const operand = try sema.resolveInst(zir_operand);
9476 if (zir_dest_type == .var_args_param) return operand;
9488 if (zir_dest_type == .var_args_param_type) return operand;
94779489 const dest_ty = sema.resolveType(block, src, zir_dest_type) catch |err| switch (err) {
94789490 error.GenericPoison => return operand,
94799491 else => |e| return e,
94809492 };
9481 if (dest_ty.zigTypeTag() == .NoReturn) {
9493 if (dest_ty.zigTypeTag(mod) == .NoReturn) {
94829494 return sema.fail(block, src, "cannot cast to noreturn", .{});
94839495 }
94849496 const is_ret = if (Zir.refToIndex(zir_dest_type)) |ptr_index|
......@@ -9495,15 +9507,19 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
94959507 const tracy = trace(@src());
94969508 defer tracy.end();
94979509
9510 const mod = sema.mod;
94989511 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
94999512 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
95009513 const ptr = try sema.resolveInst(inst_data.operand);
95019514 const ptr_ty = sema.typeOf(ptr);
9502 if (!ptr_ty.isPtrAtRuntime()) {
9503 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)});
9515 if (!ptr_ty.isPtrAtRuntime(mod)) {
9516 return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(mod)});
95049517 }
95059518 if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| {
9506 return sema.addConstant(Type.usize, ptr_val);
9519 return sema.addConstant(
9520 Type.usize,
9521 try mod.intValue(Type.usize, (try ptr_val.getUnsignedIntAdvanced(mod, sema)).?),
9522 );
95079523 }
95089524 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
95099525 return block.addUnOp(.ptrtoint, ptr);
......@@ -9513,11 +9529,12 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
95139529 const tracy = trace(@src());
95149530 defer tracy.end();
95159531
9532 const mod = sema.mod;
95169533 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
95179534 const src = inst_data.src();
95189535 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
95199536 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
9520 const field_name = sema.code.nullTerminatedString(extra.field_name_start);
9537 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));
95219538 const object = try sema.resolveInst(extra.lhs);
95229539 return sema.fieldVal(block, src, object, field_name, field_name_src);
95239540}
......@@ -9526,11 +9543,12 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index, initializing: b
95269543 const tracy = trace(@src());
95279544 defer tracy.end();
95289545
9546 const mod = sema.mod;
95299547 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
95309548 const src = inst_data.src();
95319549 const field_name_src: LazySrcLoc = .{ .node_offset_field_name = inst_data.src_node };
95329550 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
9533 const field_name = sema.code.nullTerminatedString(extra.field_name_start);
9551 const field_name = try mod.intern_pool.getOrPutString(sema.gpa, sema.code.nullTerminatedString(extra.field_name_start));
95349552 const object_ptr = try sema.resolveInst(extra.lhs);
95359553 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, initializing);
95369554}
......@@ -9544,7 +9562,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
95449562 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
95459563 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
95469564 const object = try sema.resolveInst(extra.lhs);
9547 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name, "field name must be comptime-known");
9565 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, "field name must be comptime-known");
95489566 return sema.fieldVal(block, src, object, field_name, field_name_src);
95499567}
95509568
......@@ -9557,7 +9575,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
95579575 const field_name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
95589576 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data;
95599577 const object_ptr = try sema.resolveInst(extra.lhs);
9560 const field_name = try sema.resolveConstString(block, field_name_src, extra.field_name, "field name must be comptime-known");
9578 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, "field name must be comptime-known");
95619579 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false);
95629580}
95639581
......@@ -9586,31 +9604,31 @@ fn intCast(
95869604 operand_src: LazySrcLoc,
95879605 runtime_safety: bool,
95889606) CompileError!Air.Inst.Ref {
9607 const mod = sema.mod;
95899608 const operand_ty = sema.typeOf(operand);
95909609 const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, dest_ty_src);
95919610 const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src);
95929611
95939612 if (try sema.isComptimeKnown(operand)) {
95949613 return sema.coerce(block, dest_ty, operand, operand_src);
9595 } else if (dest_scalar_ty.zigTypeTag() == .ComptimeInt) {
9614 } else if (dest_scalar_ty.zigTypeTag(mod) == .ComptimeInt) {
95969615 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{});
95979616 }
95989617
95999618 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src);
9600 const is_vector = dest_ty.zigTypeTag() == .Vector;
9619 const is_vector = dest_ty.zigTypeTag(mod) == .Vector;
96019620
96029621 if ((try sema.typeHasOnePossibleValue(dest_ty))) |opv| {
96039622 // requirement: intCast(u0, input) iff input == 0
96049623 if (runtime_safety and block.wantSafety()) {
96059624 try sema.requireRuntimeBlock(block, src, operand_src);
9606 const target = sema.mod.getTarget();
9607 const wanted_info = dest_scalar_ty.intInfo(target);
9625 const wanted_info = dest_scalar_ty.intInfo(mod);
96089626 const wanted_bits = wanted_info.bits;
96099627
96109628 if (wanted_bits == 0) {
96119629 const ok = if (is_vector) ok: {
9612 const zeros = try Value.Tag.repeated.create(sema.arena, Value.zero);
9613 const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);
9630 const zeros = try sema.splat(operand_ty, try mod.intValue(operand_scalar_ty, 0));
9631 const zero_inst = try sema.addConstant(operand_ty, zeros);
96149632 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
96159633 const all_in_range = try block.addInst(.{
96169634 .tag = .reduce,
......@@ -9618,7 +9636,7 @@ fn intCast(
96189636 });
96199637 break :ok all_in_range;
96209638 } else ok: {
9621 const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero);
9639 const zero_inst = try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0));
96229640 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
96239641 break :ok is_in_range;
96249642 };
......@@ -9631,9 +9649,8 @@ fn intCast(
96319649
96329650 try sema.requireRuntimeBlock(block, src, operand_src);
96339651 if (runtime_safety and block.wantSafety()) {
9634 const target = sema.mod.getTarget();
9635 const actual_info = operand_scalar_ty.intInfo(target);
9636 const wanted_info = dest_scalar_ty.intInfo(target);
9652 const actual_info = operand_scalar_ty.intInfo(mod);
9653 const wanted_info = dest_scalar_ty.intInfo(mod);
96379654 const actual_bits = actual_info.bits;
96389655 const wanted_bits = wanted_info.bits;
96399656 const actual_value_bits = actual_bits - @boolToInt(actual_info.signedness == .signed);
......@@ -9642,26 +9659,24 @@ fn intCast(
96429659 // range shrinkage
96439660 // requirement: int value fits into target type
96449661 if (wanted_value_bits < actual_value_bits) {
9645 const dest_max_val_scalar = try dest_scalar_ty.maxInt(sema.arena, target);
9646 const dest_max_val = if (is_vector)
9647 try Value.Tag.repeated.create(sema.arena, dest_max_val_scalar)
9648 else
9649 dest_max_val_scalar;
9662 const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_scalar_ty);
9663 const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar);
96509664 const dest_max = try sema.addConstant(operand_ty, dest_max_val);
96519665 const diff = try block.addBinOp(.subwrap, dest_max, operand);
96529666
96539667 if (actual_info.signedness == .signed) {
96549668 // Reinterpret the sign-bit as part of the value. This will make
96559669 // negative differences (`operand` > `dest_max`) appear too big.
9656 const unsigned_operand_ty = try Type.Tag.int_unsigned.create(sema.arena, actual_bits);
9670 const unsigned_operand_ty = try mod.intType(.unsigned, actual_bits);
96579671 const diff_unsigned = try block.addBitCast(unsigned_operand_ty, diff);
96589672
96599673 // If the destination type is signed, then we need to double its
96609674 // range to account for negative values.
96619675 const dest_range_val = if (wanted_info.signedness == .signed) range_val: {
9662 const range_minus_one = try dest_max_val.shl(Value.one, unsigned_operand_ty, sema.arena, sema.mod);
9663 break :range_val try sema.intAdd(range_minus_one, Value.one, unsigned_operand_ty);
9664 } else dest_max_val;
9676 const one = try mod.intValue(unsigned_operand_ty, 1);
9677 const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, mod);
9678 break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty, undefined);
9679 } else try mod.getCoerced(dest_max_val, unsigned_operand_ty);
96659680 const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
96669681
96679682 const ok = if (is_vector) ok: {
......@@ -9701,7 +9716,8 @@ fn intCast(
97019716 // no shrinkage, yes sign loss
97029717 // requirement: signed to unsigned >= 0
97039718 const ok = if (is_vector) ok: {
9704 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
9719 const scalar_zero = try mod.intValue(operand_scalar_ty, 0);
9720 const zero_val = try sema.splat(operand_ty, scalar_zero);
97059721 const zero_inst = try sema.addConstant(operand_ty, zero_val);
97069722 const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
97079723 const all_in_range = try block.addInst(.{
......@@ -9713,7 +9729,7 @@ fn intCast(
97139729 });
97149730 break :ok all_in_range;
97159731 } else ok: {
9716 const zero_inst = try sema.addConstant(operand_ty, Value.zero);
9732 const zero_inst = try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0));
97179733 const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst);
97189734 break :ok is_in_range;
97199735 };
......@@ -9727,6 +9743,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97279743 const tracy = trace(@src());
97289744 defer tracy.end();
97299745
9746 const mod = sema.mod;
97309747 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
97319748 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
97329749 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
......@@ -9735,7 +9752,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97359752 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
97369753 const operand = try sema.resolveInst(extra.rhs);
97379754 const operand_ty = sema.typeOf(operand);
9738 switch (dest_ty.zigTypeTag()) {
9755 switch (dest_ty.zigTypeTag(mod)) {
97399756 .AnyFrame,
97409757 .ComptimeFloat,
97419758 .ComptimeInt,
......@@ -9751,14 +9768,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97519768 .Type,
97529769 .Undefined,
97539770 .Void,
9754 => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)}),
9771 => return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)}),
97559772
97569773 .Enum => {
97579774 const msg = msg: {
9758 const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)});
9775 const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)});
97599776 errdefer msg.destroy(sema.gpa);
9760 switch (operand_ty.zigTypeTag()) {
9761 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(sema.mod)}),
9777 switch (operand_ty.zigTypeTag(mod)) {
9778 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToEnum to cast from '{}'", .{operand_ty.fmt(mod)}),
97629779 else => {},
97639780 }
97649781
......@@ -9769,11 +9786,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97699786
97709787 .Pointer => {
97719788 const msg = msg: {
9772 const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(sema.mod)});
9789 const msg = try sema.errMsg(block, dest_ty_src, "cannot @bitCast to '{}'", .{dest_ty.fmt(mod)});
97739790 errdefer msg.destroy(sema.gpa);
9774 switch (operand_ty.zigTypeTag()) {
9775 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(sema.mod)}),
9776 .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(sema.mod)}),
9791 switch (operand_ty.zigTypeTag(mod)) {
9792 .Int, .ComptimeInt => try sema.errNote(block, dest_ty_src, msg, "use @intToPtr to cast from '{}'", .{operand_ty.fmt(mod)}),
9793 .Pointer => try sema.errNote(block, dest_ty_src, msg, "use @ptrCast to cast from '{}'", .{operand_ty.fmt(mod)}),
97779794 else => {},
97789795 }
97799796
......@@ -9781,14 +9798,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97819798 };
97829799 return sema.failWithOwnedErrorMsg(msg);
97839800 },
9784 .Struct, .Union => if (dest_ty.containerLayout() == .Auto) {
9785 const container = switch (dest_ty.zigTypeTag()) {
9801 .Struct, .Union => if (dest_ty.containerLayout(mod) == .Auto) {
9802 const container = switch (dest_ty.zigTypeTag(mod)) {
97869803 .Struct => "struct",
97879804 .Union => "union",
97889805 else => unreachable,
97899806 };
97909807 return sema.fail(block, dest_ty_src, "cannot @bitCast to '{}'; {s} does not have a guaranteed in-memory layout", .{
9791 dest_ty.fmt(sema.mod), container,
9808 dest_ty.fmt(mod), container,
97929809 });
97939810 },
97949811
......@@ -9799,7 +9816,7 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
97999816 .Vector,
98009817 => {},
98019818 }
9802 switch (operand_ty.zigTypeTag()) {
9819 switch (operand_ty.zigTypeTag(mod)) {
98039820 .AnyFrame,
98049821 .ComptimeFloat,
98059822 .ComptimeInt,
......@@ -9815,14 +9832,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
98159832 .Type,
98169833 .Undefined,
98179834 .Void,
9818 => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)}),
9835 => return sema.fail(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)}),
98199836
98209837 .Enum => {
98219838 const msg = msg: {
9822 const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)});
9839 const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)});
98239840 errdefer msg.destroy(sema.gpa);
9824 switch (dest_ty.zigTypeTag()) {
9825 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}),
9841 switch (dest_ty.zigTypeTag(mod)) {
9842 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @enumToInt to cast to '{}'", .{dest_ty.fmt(mod)}),
98269843 else => {},
98279844 }
98289845
......@@ -9832,11 +9849,11 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
98329849 },
98339850 .Pointer => {
98349851 const msg = msg: {
9835 const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(sema.mod)});
9852 const msg = try sema.errMsg(block, operand_src, "cannot @bitCast from '{}'", .{operand_ty.fmt(mod)});
98369853 errdefer msg.destroy(sema.gpa);
9837 switch (dest_ty.zigTypeTag()) {
9838 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(sema.mod)}),
9839 .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(sema.mod)}),
9854 switch (dest_ty.zigTypeTag(mod)) {
9855 .Int, .ComptimeInt => try sema.errNote(block, operand_src, msg, "use @ptrToInt to cast to '{}'", .{dest_ty.fmt(mod)}),
9856 .Pointer => try sema.errNote(block, operand_src, msg, "use @ptrCast to cast to '{}'", .{dest_ty.fmt(mod)}),
98409857 else => {},
98419858 }
98429859
......@@ -9844,14 +9861,14 @@ fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
98449861 };
98459862 return sema.failWithOwnedErrorMsg(msg);
98469863 },
9847 .Struct, .Union => if (operand_ty.containerLayout() == .Auto) {
9848 const container = switch (operand_ty.zigTypeTag()) {
9864 .Struct, .Union => if (operand_ty.containerLayout(mod) == .Auto) {
9865 const container = switch (operand_ty.zigTypeTag(mod)) {
98499866 .Struct => "struct",
98509867 .Union => "union",
98519868 else => unreachable,
98529869 };
98539870 return sema.fail(block, operand_src, "cannot @bitCast from '{}'; {s} does not have a guaranteed in-memory layout", .{
9854 operand_ty.fmt(sema.mod), container,
9871 operand_ty.fmt(mod), container,
98559872 });
98569873 },
98579874
......@@ -9869,6 +9886,7 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
98699886 const tracy = trace(@src());
98709887 defer tracy.end();
98719888
9889 const mod = sema.mod;
98729890 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
98739891 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
98749892 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
......@@ -9877,31 +9895,31 @@ fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
98779895 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
98789896 const operand = try sema.resolveInst(extra.rhs);
98799897
9880 const target = sema.mod.getTarget();
9881 const dest_is_comptime_float = switch (dest_ty.zigTypeTag()) {
9898 const target = mod.getTarget();
9899 const dest_is_comptime_float = switch (dest_ty.zigTypeTag(mod)) {
98829900 .ComptimeFloat => true,
98839901 .Float => false,
98849902 else => return sema.fail(
98859903 block,
98869904 dest_ty_src,
98879905 "expected float type, found '{}'",
9888 .{dest_ty.fmt(sema.mod)},
9906 .{dest_ty.fmt(mod)},
98899907 ),
98909908 };
98919909
98929910 const operand_ty = sema.typeOf(operand);
9893 switch (operand_ty.zigTypeTag()) {
9911 switch (operand_ty.zigTypeTag(mod)) {
98949912 .ComptimeFloat, .Float, .ComptimeInt => {},
98959913 else => return sema.fail(
98969914 block,
98979915 operand_src,
98989916 "expected float type, found '{}'",
9899 .{operand_ty.fmt(sema.mod)},
9917 .{operand_ty.fmt(mod)},
99009918 ),
99019919 }
99029920
99039921 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
9904 return sema.addConstant(dest_ty, try operand_val.floatCast(sema.arena, dest_ty, target));
9922 return sema.addConstant(dest_ty, try operand_val.floatCast(dest_ty, mod));
99059923 }
99069924 if (dest_is_comptime_float) {
99079925 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_float'", .{});
......@@ -9944,20 +9962,21 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
99449962 const tracy = trace(@src());
99459963 defer tracy.end();
99469964
9965 const mod = sema.mod;
99479966 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
99489967 const src = inst_data.src();
99499968 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
99509969 const array_ptr = try sema.resolveInst(extra.lhs);
99519970 const elem_index = try sema.resolveInst(extra.rhs);
99529971 const indexable_ty = sema.typeOf(array_ptr);
9953 if (indexable_ty.zigTypeTag() != .Pointer) {
9972 if (indexable_ty.zigTypeTag(mod) != .Pointer) {
99549973 const capture_src: LazySrcLoc = .{ .for_capture_from_input = inst_data.src_node };
99559974 const msg = msg: {
99569975 const msg = try sema.errMsg(block, capture_src, "pointer capture of non pointer type '{}'", .{
9957 indexable_ty.fmt(sema.mod),
9976 indexable_ty.fmt(mod),
99589977 });
99599978 errdefer msg.destroy(sema.gpa);
9960 if (indexable_ty.zigTypeTag() == .Array) {
9979 if (indexable_ty.zigTypeTag(mod) == .Array) {
99619980 try sema.errNote(block, src, msg, "consider using '&' here", .{});
99629981 }
99639982 break :msg msg;
......@@ -10054,7 +10073,7 @@ fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1005410073 const array_ptr = try sema.resolveInst(extra.lhs);
1005510074 const start = try sema.resolveInst(extra.start);
1005610075 const len = try sema.resolveInst(extra.len);
10057 const sentinel = try sema.resolveInst(extra.sentinel);
10076 const sentinel = if (extra.sentinel == .none) .none else try sema.resolveInst(extra.sentinel);
1005810077 const ptr_src: LazySrcLoc = .{ .node_offset_slice_ptr = inst_data.src_node };
1005910078 const start_src: LazySrcLoc = .{ .node_offset_slice_start = extra.start_src_node_offset };
1006010079 const end_src: LazySrcLoc = .{ .node_offset_slice_end = inst_data.src_node };
......@@ -10076,6 +10095,8 @@ fn zirSwitchCapture(
1007610095 const tracy = trace(@src());
1007710096 defer tracy.end();
1007810097
10098 const mod = sema.mod;
10099 const gpa = sema.gpa;
1007910100 const zir_datas = sema.code.instructions.items(.data);
1008010101 const capture_info = zir_datas[inst].switch_capture;
1008110102 const switch_info = zir_datas[capture_info.switch_inst].pl_node;
......@@ -10087,47 +10108,49 @@ fn zirSwitchCapture(
1008710108 const operand_is_ref = cond_tag == .switch_cond_ref;
1008810109 const operand_ptr = try sema.resolveInst(cond_info.operand);
1008910110 const operand_ptr_ty = sema.typeOf(operand_ptr);
10090 const operand_ty = if (operand_is_ref) operand_ptr_ty.childType() else operand_ptr_ty;
10111 const operand_ty = if (operand_is_ref) operand_ptr_ty.childType(mod) else operand_ptr_ty;
1009110112
1009210113 if (block.inline_case_capture != .none) {
1009310114 const item_val = sema.resolveConstValue(block, .unneeded, block.inline_case_capture, undefined) catch unreachable;
10094 if (operand_ty.zigTypeTag() == .Union) {
10095 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(item_val, sema.mod).?);
10096 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;
10115 const resolved_item_val = try sema.resolveLazyValue(item_val);
10116 if (operand_ty.zigTypeTag(mod) == .Union) {
10117 const field_index = @intCast(u32, operand_ty.unionTagFieldIndex(resolved_item_val, mod).?);
10118 const union_obj = mod.typeToUnion(operand_ty).?;
1009710119 const field_ty = union_obj.fields.values()[field_index].ty;
1009810120 if (try sema.resolveDefinedValue(block, sema.src, operand_ptr)) |union_val| {
1009910121 if (is_ref) {
10100 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
10122 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
1010110123 .pointee_type = field_ty,
10102 .mutable = operand_ptr_ty.ptrIsMutable(),
10103 .@"volatile" = operand_ptr_ty.isVolatilePtr(),
10104 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(),
10124 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10125 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10126 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
1010510127 });
10106 return sema.addConstant(
10107 ptr_field_ty,
10108 try Value.Tag.field_ptr.create(sema.arena, .{
10109 .container_ptr = union_val,
10110 .container_ty = operand_ty,
10111 .field_index = field_index,
10112 }),
10113 );
10128 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
10129 .ty = ptr_field_ty.toIntern(),
10130 .addr = .{ .field = .{
10131 .base = union_val.toIntern(),
10132 .index = field_index,
10133 } },
10134 } })).toValue());
1011410135 }
10115 const tag_and_val = union_val.castTag(.@"union").?.data;
10116 return sema.addConstant(field_ty, tag_and_val.val);
10136 return sema.addConstant(
10137 field_ty,
10138 mod.intern_pool.indexToKey(union_val.toIntern()).un.val.toValue(),
10139 );
1011710140 }
1011810141 if (is_ref) {
10119 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
10142 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
1012010143 .pointee_type = field_ty,
10121 .mutable = operand_ptr_ty.ptrIsMutable(),
10122 .@"volatile" = operand_ptr_ty.isVolatilePtr(),
10123 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(),
10144 .mutable = operand_ptr_ty.ptrIsMutable(mod),
10145 .@"volatile" = operand_ptr_ty.isVolatilePtr(mod),
10146 .@"addrspace" = operand_ptr_ty.ptrAddressSpace(mod),
1012410147 });
1012510148 return block.addStructFieldPtr(operand_ptr, field_index, ptr_field_ty);
1012610149 } else {
1012710150 return block.addStructFieldVal(operand_ptr, field_index, field_ty);
1012810151 }
1012910152 } else if (is_ref) {
10130 return sema.addConstantMaybeRef(block, operand_ty, item_val, true);
10153 return sema.addConstantMaybeRef(block, operand_ty, resolved_item_val, true);
1013110154 } else {
1013210155 return block.inline_case_capture;
1013310156 }
......@@ -10144,7 +10167,7 @@ fn zirSwitchCapture(
1014410167 return operand_ptr;
1014510168 }
1014610169
10147 switch (operand_ty.zigTypeTag()) {
10170 switch (operand_ty.zigTypeTag(mod)) {
1014810171 .ErrorSet => if (block.switch_else_err_ty) |some| {
1014910172 return sema.bitCast(block, some, operand, operand_src, null);
1015010173 } else {
......@@ -10162,14 +10185,14 @@ fn zirSwitchCapture(
1016210185 switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item,
1016310186 };
1016410187
10165 switch (operand_ty.zigTypeTag()) {
10188 switch (operand_ty.zigTypeTag(mod)) {
1016610189 .Union => {
10167 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;
10190 const union_obj = mod.typeToUnion(operand_ty).?;
1016810191 const first_item = try sema.resolveInst(items[0]);
1016910192 // Previous switch validation ensured this will succeed
1017010193 const first_item_val = sema.resolveConstValue(block, .unneeded, first_item, "") catch unreachable;
1017110194
10172 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, sema.mod).?);
10195 const first_field_index = @intCast(u32, operand_ty.unionTagFieldIndex(first_item_val, mod).?);
1017310196 const first_field = union_obj.fields.values()[first_field_index];
1017410197
1017510198 for (items[1..], 0..) |item, i| {
......@@ -10177,22 +10200,22 @@ fn zirSwitchCapture(
1017710200 // Previous switch validation ensured this will succeed
1017810201 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
1017910202
10180 const field_index = operand_ty.unionTagFieldIndex(item_val, sema.mod).?;
10203 const field_index = operand_ty.unionTagFieldIndex(item_val, mod).?;
1018110204 const field = union_obj.fields.values()[field_index];
10182 if (!field.ty.eql(first_field.ty, sema.mod)) {
10205 if (!field.ty.eql(first_field.ty, mod)) {
1018310206 const msg = msg: {
1018410207 const raw_capture_src = Module.SwitchProngSrc{ .multi_capture = capture_info.prong_index };
10185 const capture_src = raw_capture_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_info.src_node, .first);
10208 const capture_src = raw_capture_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
1018610209
1018710210 const msg = try sema.errMsg(block, capture_src, "capture group with incompatible types", .{});
10188 errdefer msg.destroy(sema.gpa);
10211 errdefer msg.destroy(gpa);
1018910212
1019010213 const raw_first_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 0 } };
10191 const first_item_src = raw_first_item_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_info.src_node, .first);
10214 const first_item_src = raw_first_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
1019210215 const raw_item_src = Module.SwitchProngSrc{ .multi = .{ .prong = capture_info.prong_index, .item = 1 + @intCast(u32, i) } };
10193 const item_src = raw_item_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_info.src_node, .first);
10194 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(sema.mod)});
10195 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(sema.mod)});
10216 const item_src = raw_item_src.resolve(mod, mod.declPtr(block.src_decl), switch_info.src_node, .first);
10217 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(mod)});
10218 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(mod)});
1019610219 break :msg msg;
1019710220 };
1019810221 return sema.failWithOwnedErrorMsg(msg);
......@@ -10200,21 +10223,20 @@ fn zirSwitchCapture(
1020010223 }
1020110224
1020210225 if (is_ref) {
10203 const field_ty_ptr = try Type.ptr(sema.arena, sema.mod, .{
10226 const field_ty_ptr = try Type.ptr(sema.arena, mod, .{
1020410227 .pointee_type = first_field.ty,
1020510228 .@"addrspace" = .generic,
10206 .mutable = operand_ptr_ty.ptrIsMutable(),
10229 .mutable = operand_ptr_ty.ptrIsMutable(mod),
1020710230 });
1020810231
1020910232 if (try sema.resolveDefinedValue(block, operand_src, operand_ptr)) |op_ptr_val| {
10210 return sema.addConstant(
10211 field_ty_ptr,
10212 try Value.Tag.field_ptr.create(sema.arena, .{
10213 .container_ptr = op_ptr_val,
10214 .container_ty = operand_ty,
10215 .field_index = first_field_index,
10216 }),
10217 );
10233 return sema.addConstant(field_ty_ptr, (try mod.intern(.{ .ptr = .{
10234 .ty = field_ty_ptr.toIntern(),
10235 .addr = .{ .field = .{
10236 .base = op_ptr_val.toIntern(),
10237 .index = first_field_index,
10238 } },
10239 } })).toValue());
1021810240 }
1021910241 try sema.requireRuntimeBlock(block, operand_src, null);
1022010242 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
......@@ -10223,7 +10245,7 @@ fn zirSwitchCapture(
1022310245 if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| {
1022410246 return sema.addConstant(
1022510247 first_field.ty,
10226 operand_val.castTag(.@"union").?.data.val,
10248 mod.intern_pool.indexToKey(operand_val.toIntern()).un.val.toValue(),
1022710249 );
1022810250 }
1022910251 try sema.requireRuntimeBlock(block, operand_src, null);
......@@ -10231,28 +10253,23 @@ fn zirSwitchCapture(
1023110253 },
1023210254 .ErrorSet => {
1023310255 if (is_multi) {
10234 var names: Module.ErrorSet.NameMap = .{};
10256 var names: Module.Fn.InferredErrorSet.NameMap = .{};
1023510257 try names.ensureUnusedCapacity(sema.arena, items.len);
1023610258 for (items) |item| {
1023710259 const item_ref = try sema.resolveInst(item);
1023810260 // Previous switch validation ensured this will succeed
10239 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
10240 names.putAssumeCapacityNoClobber(
10241 item_val.getError().?,
10242 {},
10243 );
10261 const item_val = sema.resolveConstLazyValue(block, .unneeded, item_ref, "") catch unreachable;
10262 names.putAssumeCapacityNoClobber(item_val.getErrorName(mod).unwrap().?, {});
1024410263 }
10245 // names must be sorted
10246 Module.ErrorSet.sortNames(&names);
10247 const else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
10264 const else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
1024810265
1024910266 return sema.bitCast(block, else_error_ty, operand, operand_src, null);
1025010267 } else {
1025110268 const item_ref = try sema.resolveInst(items[0]);
1025210269 // Previous switch validation ensured this will succeed
10253 const item_val = sema.resolveConstValue(block, .unneeded, item_ref, "") catch unreachable;
10270 const item_val = sema.resolveConstLazyValue(block, .unneeded, item_ref, "") catch unreachable;
1025410271
10255 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);
10272 const item_ty = try mod.singleErrorSetType(item_val.getErrorName(mod).unwrap().?);
1025610273 return sema.bitCast(block, item_ty, operand, operand_src, null);
1025710274 }
1025810275 },
......@@ -10269,6 +10286,7 @@ fn zirSwitchCapture(
1026910286}
1027010287
1027110288fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
10289 const mod = sema.mod;
1027210290 const zir_datas = sema.code.instructions.items(.data);
1027310291 const inst_data = zir_datas[inst].un_tok;
1027410292 const src = inst_data.src();
......@@ -10278,12 +10296,12 @@ fn zirSwitchCaptureTag(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compile
1027810296 const cond_data = zir_datas[Zir.refToIndex(inst_data.operand).?].un_node;
1027910297 const operand_ptr = try sema.resolveInst(cond_data.operand);
1028010298 const operand_ptr_ty = sema.typeOf(operand_ptr);
10281 const operand_ty = if (is_ref) operand_ptr_ty.childType() else operand_ptr_ty;
10299 const operand_ty = if (is_ref) operand_ptr_ty.childType(mod) else operand_ptr_ty;
1028210300
10283 if (operand_ty.zigTypeTag() != .Union) {
10301 if (operand_ty.zigTypeTag(mod) != .Union) {
1028410302 const msg = msg: {
1028510303 const msg = try sema.errMsg(block, src, "cannot capture tag of non-union type '{}'", .{
10286 operand_ty.fmt(sema.mod),
10304 operand_ty.fmt(mod),
1028710305 });
1028810306 errdefer msg.destroy(sema.gpa);
1028910307 try sema.addDeclaredHereNote(msg, operand_ty);
......@@ -10301,6 +10319,7 @@ fn zirSwitchCond(
1030110319 inst: Zir.Inst.Index,
1030210320 is_ref: bool,
1030310321) CompileError!Air.Inst.Ref {
10322 const mod = sema.mod;
1030410323 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1030510324 const src = inst_data.src();
1030610325 const operand_src: LazySrcLoc = .{ .node_offset_switch_operand = inst_data.src_node };
......@@ -10311,7 +10330,7 @@ fn zirSwitchCond(
1031110330 operand_ptr;
1031210331 const operand_ty = sema.typeOf(operand);
1031310332
10314 switch (operand_ty.zigTypeTag()) {
10333 switch (operand_ty.zigTypeTag(mod)) {
1031510334 .Type,
1031610335 .Void,
1031710336 .Bool,
......@@ -10325,8 +10344,8 @@ fn zirSwitchCond(
1032510344 .ErrorSet,
1032610345 .Enum,
1032710346 => {
10328 if (operand_ty.isSlice()) {
10329 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)});
10347 if (operand_ty.isSlice(mod)) {
10348 return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(mod)});
1033010349 }
1033110350 if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| {
1033210351 return sema.addConstant(operand_ty, opv);
......@@ -10336,12 +10355,12 @@ fn zirSwitchCond(
1033610355
1033710356 .Union => {
1033810357 const union_ty = try sema.resolveTypeFields(operand_ty);
10339 const enum_ty = union_ty.unionTagType() orelse {
10358 const enum_ty = union_ty.unionTagType(mod) orelse {
1034010359 const msg = msg: {
1034110360 const msg = try sema.errMsg(block, src, "switch on union with no attached enum", .{});
1034210361 errdefer msg.destroy(sema.gpa);
10343 if (union_ty.declSrcLocOrNull(sema.mod)) |union_src| {
10344 try sema.mod.errNoteNonLazy(union_src, msg, "consider 'union(enum)' here", .{});
10362 if (union_ty.declSrcLocOrNull(mod)) |union_src| {
10363 try mod.errNoteNonLazy(union_src, msg, "consider 'union(enum)' here", .{});
1034510364 }
1034610365 break :msg msg;
1034710366 };
......@@ -10361,17 +10380,19 @@ fn zirSwitchCond(
1036110380 .Vector,
1036210381 .Frame,
1036310382 .AnyFrame,
10364 => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)}),
10383 => return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(mod)}),
1036510384 }
1036610385}
1036710386
10368const SwitchErrorSet = std.StringHashMap(Module.SwitchProngSrc);
10387const SwitchErrorSet = std.AutoHashMap(InternPool.NullTerminatedString, Module.SwitchProngSrc);
1036910388
1037010389fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1037110390 const tracy = trace(@src());
1037210391 defer tracy.end();
1037310392
10393 const mod = sema.mod;
1037410394 const gpa = sema.gpa;
10395 const ip = &mod.intern_pool;
1037510396 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1037610397 const src = inst_data.src();
1037710398 const src_node_offset = inst_data.src_node;
......@@ -10413,14 +10434,14 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1041310434 const cond_index = Zir.refToIndex(extra.data.operand).?;
1041410435 const raw_operand = sema.resolveInst(zir_data[cond_index].un_node.operand) catch unreachable;
1041510436 const target_ty = sema.typeOf(raw_operand);
10416 break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.elemType() else target_ty;
10437 break :blk if (zir_tags[cond_index] == .switch_cond_ref) target_ty.childType(mod) else target_ty;
1041710438 };
10418 const union_originally = maybe_union_ty.zigTypeTag() == .Union;
10439 const union_originally = maybe_union_ty.zigTypeTag(mod) == .Union;
1041910440
1042010441 // Duplicate checking variables later also used for `inline else`.
1042110442 var seen_enum_fields: []?Module.SwitchProngSrc = &.{};
1042210443 var seen_errors = SwitchErrorSet.init(gpa);
10423 var range_set = RangeSet.init(gpa, sema.mod);
10444 var range_set = RangeSet.init(gpa, mod);
1042410445 var true_count: u8 = 0;
1042510446 var false_count: u8 = 0;
1042610447
......@@ -10433,12 +10454,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1043310454 var empty_enum = false;
1043410455
1043510456 const operand_ty = sema.typeOf(operand);
10436 const err_set = operand_ty.zigTypeTag() == .ErrorSet;
10457 const err_set = operand_ty.zigTypeTag(mod) == .ErrorSet;
1043710458
1043810459 var else_error_ty: ?Type = null;
1043910460
1044010461 // Validate usage of '_' prongs.
10441 if (special_prong == .under and (!operand_ty.isNonexhaustiveEnum() or union_originally)) {
10462 if (special_prong == .under and (!operand_ty.isNonexhaustiveEnum(mod) or union_originally)) {
1044210463 const msg = msg: {
1044310464 const msg = try sema.errMsg(
1044410465 block,
......@@ -10459,14 +10480,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1045910480 return sema.failWithOwnedErrorMsg(msg);
1046010481 }
1046110482
10462 const target = sema.mod.getTarget();
10463
1046410483 // Validate for duplicate items, missing else prong, and invalid range.
10465 switch (operand_ty.zigTypeTag()) {
10484 switch (operand_ty.zigTypeTag(mod)) {
1046610485 .Union => unreachable, // handled in zirSwitchCond
1046710486 .Enum => {
10468 seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount());
10469 empty_enum = seen_enum_fields.len == 0 and !operand_ty.isNonexhaustiveEnum();
10487 seen_enum_fields = try gpa.alloc(?Module.SwitchProngSrc, operand_ty.enumFieldCount(mod));
10488 empty_enum = seen_enum_fields.len == 0 and !operand_ty.isNonexhaustiveEnum(mod);
1047010489 @memset(seen_enum_fields, null);
1047110490 // `range_set` is used for non-exhaustive enum values that do not correspond to any tags.
1047210491
......@@ -10521,7 +10540,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1052110540 } else true;
1052210541
1052310542 if (special_prong == .@"else") {
10524 if (all_tags_handled and !operand_ty.isNonexhaustiveEnum()) return sema.fail(
10543 if (all_tags_handled and !operand_ty.isNonexhaustiveEnum(mod)) return sema.fail(
1052510544 block,
1052610545 special_prong_src,
1052710546 "unreachable else prong; all cases already handled",
......@@ -10539,25 +10558,25 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1053910558 for (seen_enum_fields, 0..) |seen_src, i| {
1054010559 if (seen_src != null) continue;
1054110560
10542 const field_name = operand_ty.enumFieldName(i);
10561 const field_name = operand_ty.enumFieldName(i, mod);
1054310562 try sema.addFieldErrNote(
1054410563 operand_ty,
1054510564 i,
1054610565 msg,
10547 "unhandled enumeration value: '{s}'",
10548 .{field_name},
10566 "unhandled enumeration value: '{}'",
10567 .{field_name.fmt(&mod.intern_pool)},
1054910568 );
1055010569 }
10551 try sema.mod.errNoteNonLazy(
10552 operand_ty.declSrcLoc(sema.mod),
10570 try mod.errNoteNonLazy(
10571 operand_ty.declSrcLoc(mod),
1055310572 msg,
1055410573 "enum '{}' declared here",
10555 .{operand_ty.fmt(sema.mod)},
10574 .{operand_ty.fmt(mod)},
1055610575 );
1055710576 break :msg msg;
1055810577 };
1055910578 return sema.failWithOwnedErrorMsg(msg);
10560 } else if (special_prong == .none and operand_ty.isNonexhaustiveEnum() and !union_originally) {
10579 } else if (special_prong == .none and operand_ty.isNonexhaustiveEnum(mod) and !union_originally) {
1056110580 return sema.fail(
1056210581 block,
1056310582 src,
......@@ -10614,7 +10633,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1061410633
1061510634 try sema.resolveInferredErrorSetTy(block, src, operand_ty);
1061610635
10617 if (operand_ty.isAnyError()) {
10636 if (operand_ty.isAnyError(mod)) {
1061810637 if (special_prong != .@"else") {
1061910638 return sema.fail(
1062010639 block,
......@@ -10628,7 +10647,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1062810647 var maybe_msg: ?*Module.ErrorMsg = null;
1062910648 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
1063010649
10631 for (operand_ty.errorSetNames()) |error_name| {
10650 for (operand_ty.errorSetNames(mod)) |error_name| {
1063210651 if (!seen_errors.contains(error_name) and special_prong != .@"else") {
1063310652 const msg = maybe_msg orelse blk: {
1063410653 maybe_msg = try sema.errMsg(
......@@ -10644,8 +10663,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1064410663 block,
1064510664 src,
1064610665 msg,
10647 "unhandled error value: 'error.{s}'",
10648 .{error_name},
10666 "unhandled error value: 'error.{}'",
10667 .{error_name.fmt(ip)},
1064910668 );
1065010669 }
1065110670 }
......@@ -10656,7 +10675,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1065610675 return sema.failWithOwnedErrorMsg(msg);
1065710676 }
1065810677
10659 if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) {
10678 if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames(mod).len) {
1066010679 // In order to enable common patterns for generic code allow simple else bodies
1066110680 // else => unreachable,
1066210681 // else => return,
......@@ -10693,18 +10712,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1069310712 );
1069410713 }
1069510714
10696 const error_names = operand_ty.errorSetNames();
10697 var names: Module.ErrorSet.NameMap = .{};
10715 const error_names = operand_ty.errorSetNames(mod);
10716 var names: Module.Fn.InferredErrorSet.NameMap = .{};
1069810717 try names.ensureUnusedCapacity(sema.arena, error_names.len);
1069910718 for (error_names) |error_name| {
1070010719 if (seen_errors.contains(error_name)) continue;
1070110720
1070210721 names.putAssumeCapacityNoClobber(error_name, {});
1070310722 }
10704
10705 // names must be sorted
10706 Module.ErrorSet.sortNames(&names);
10707 else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
10723 // No need to keep the hash map metadata correct; here we
10724 // extract the (sorted) keys only.
10725 else_error_ty = try mod.errorSetFromUnsortedNames(names.keys());
1070810726 }
1070910727 },
1071010728 .Int, .ComptimeInt => {
......@@ -10722,7 +10740,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1072210740 block,
1072310741 &range_set,
1072410742 item_ref,
10725 operand_ty,
1072610743 src_node_offset,
1072710744 .{ .scalar = scalar_i },
1072810745 );
......@@ -10745,7 +10762,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1074510762 block,
1074610763 &range_set,
1074710764 item_ref,
10748 operand_ty,
1074910765 src_node_offset,
1075010766 .{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } },
1075110767 );
......@@ -10763,7 +10779,6 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1076310779 &range_set,
1076410780 item_first,
1076510781 item_last,
10766 operand_ty,
1076710782 src_node_offset,
1076810783 .{ .range = .{ .prong = multi_i, .item = range_i } },
1076910784 );
......@@ -10774,13 +10789,10 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1077410789 }
1077510790
1077610791 check_range: {
10777 if (operand_ty.zigTypeTag() == .Int) {
10778 var arena = std.heap.ArenaAllocator.init(gpa);
10779 defer arena.deinit();
10780
10781 const min_int = try operand_ty.minInt(arena.allocator(), target);
10782 const max_int = try operand_ty.maxInt(arena.allocator(), target);
10783 if (try range_set.spans(min_int, max_int, operand_ty)) {
10792 if (operand_ty.zigTypeTag(mod) == .Int) {
10793 const min_int = try operand_ty.minInt(mod, operand_ty);
10794 const max_int = try operand_ty.maxInt(mod, operand_ty);
10795 if (try range_set.spans(min_int.toIntern(), max_int.toIntern())) {
1078410796 if (special_prong == .@"else") {
1078510797 return sema.fail(
1078610798 block,
......@@ -10878,15 +10890,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1087810890 block,
1087910891 src,
1088010892 "else prong required when switching on type '{}'",
10881 .{operand_ty.fmt(sema.mod)},
10893 .{operand_ty.fmt(mod)},
1088210894 );
1088310895 }
1088410896
10885 var seen_values = ValueSrcMap.initContext(gpa, .{
10886 .ty = operand_ty,
10887 .mod = sema.mod,
10888 });
10889 defer seen_values.deinit();
10897 var seen_values = ValueSrcMap{};
10898 defer seen_values.deinit(gpa);
1089010899
1089110900 var extra_index: usize = special.end;
1089210901 {
......@@ -10948,7 +10957,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1094810957 .ComptimeFloat,
1094910958 .Float,
1095010959 => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{
10951 operand_ty.fmt(sema.mod),
10960 operand_ty.fmt(mod),
1095210961 }),
1095310962 }
1095410963
......@@ -10991,6 +11000,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1099111000 defer merges.deinit(gpa);
1099211001
1099311002 if (try sema.resolveDefinedValue(&child_block, src, operand)) |operand_val| {
11003 const resolved_operand_val = try sema.resolveLazyValue(operand_val);
1099411004 var extra_index: usize = special.end;
1099511005 {
1099611006 var scalar_i: usize = 0;
......@@ -11005,8 +11015,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1100511015
1100611016 const item = try sema.resolveInst(item_ref);
1100711017 // Validation above ensured these will succeed.
11008 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11009 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11018 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;
11019 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {
1101011020 if (is_inline) child_block.inline_case_capture = operand;
1101111021
1101211022 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
......@@ -11031,8 +11041,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1103111041 for (items) |item_ref| {
1103211042 const item = try sema.resolveInst(item_ref);
1103311043 // Validation above ensured these will succeed.
11034 const item_val = sema.resolveConstValue(&child_block, .unneeded, item, "") catch unreachable;
11035 if (operand_val.eql(item_val, operand_ty, sema.mod)) {
11044 const item_val = sema.resolveConstLazyValue(&child_block, .unneeded, item, "") catch unreachable;
11045 if (resolved_operand_val.eql(item_val, operand_ty, mod)) {
1103611046 if (is_inline) child_block.inline_case_capture = operand;
1103711047
1103811048 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
......@@ -11050,8 +11060,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1105011060 // Validation above ensured these will succeed.
1105111061 const first_tv = sema.resolveInstConst(&child_block, .unneeded, item_first, "") catch unreachable;
1105211062 const last_tv = sema.resolveInstConst(&child_block, .unneeded, item_last, "") catch unreachable;
11053 if ((try sema.compareAll(operand_val, .gte, first_tv.val, operand_ty)) and
11054 (try sema.compareAll(operand_val, .lte, last_tv.val, operand_ty)))
11063 if ((try sema.compareAll(resolved_operand_val, .gte, first_tv.val, operand_ty)) and
11064 (try sema.compareAll(resolved_operand_val, .lte, last_tv.val, operand_ty)))
1105511065 {
1105611066 if (is_inline) child_block.inline_case_capture = operand;
1105711067 if (err_set) try sema.maybeErrorUnwrapComptime(&child_block, body, operand);
......@@ -11080,8 +11090,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1108011090 if (err_set and try sema.maybeErrorUnwrap(block, special.body, operand)) {
1108111091 return Air.Inst.Ref.unreachable_value;
1108211092 }
11083 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag() == .Enum and
11084 (!operand_ty.isNonexhaustiveEnum() or union_originally))
11093 if (mod.backendSupportsFeature(.is_named_enum_value) and block.wantSafety() and operand_ty.zigTypeTag(mod) == .Enum and
11094 (!operand_ty.isNonexhaustiveEnum(mod) or union_originally))
1108511095 {
1108611096 try sema.zirDbgStmt(block, cond_dbg_node_index);
1108711097 const ok = try block.addUnOp(.is_named_enum_value, operand);
......@@ -11121,7 +11131,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1112111131 const body = sema.code.extra[extra_index..][0..body_len];
1112211132 extra_index += body_len;
1112311133
11124 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope);
11134 var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope);
1112511135 defer wip_captures.deinit();
1112611136
1112711137 case_block.instructions.shrinkRetainingCapacity(0);
......@@ -11133,9 +11143,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1113311143 // `item` is already guaranteed to be constant known.
1113411144
1113511145 const analyze_body = if (union_originally) blk: {
11136 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
11137 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
11138 break :blk field_ty.zigTypeTag() != .NoReturn;
11146 const item_val = sema.resolveConstLazyValue(block, .unneeded, item, "") catch unreachable;
11147 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11148 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
1113911149 } else true;
1114011150
1114111151 if (err_set and try sema.maybeErrorUnwrap(&case_block, body, operand)) {
......@@ -11197,9 +11207,12 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1119711207 const item_last_ref = try sema.resolveInst(last_ref);
1119811208 const item_last = sema.resolveConstValue(block, .unneeded, item_last_ref, undefined) catch unreachable;
1119911209
11200 while (item.compareAll(.lte, item_last, operand_ty, sema.mod)) : ({
11210 while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({
1120111211 // Previous validation has resolved any possible lazy values.
11202 item = try sema.intAddScalar(item, Value.one);
11212 item = sema.intAddScalar(item, try mod.intValue(operand_ty, 1), operand_ty) catch |err| switch (err) {
11213 error.Overflow => unreachable,
11214 else => |e| return e,
11215 };
1120311216 }) {
1120411217 cases_len += 1;
1120511218
......@@ -11212,8 +11225,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1121211225 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
1121311226 error.NeededSourceLocation => {
1121411227 const case_src = Module.SwitchProngSrc{ .range = .{ .prong = multi_i, .item = range_i } };
11215 const decl = sema.mod.declPtr(case_block.src_decl);
11216 try sema.emitBackwardBranch(block, case_src.resolve(sema.gpa, decl, src_node_offset, .none));
11228 const decl = mod.declPtr(case_block.src_decl);
11229 try sema.emitBackwardBranch(block, case_src.resolve(mod, decl, src_node_offset, .none));
1121711230 unreachable;
1121811231 },
1121911232 else => return err,
......@@ -11241,15 +11254,15 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1124111254
1124211255 const analyze_body = if (union_originally) blk: {
1124311256 const item_val = sema.resolveConstValue(block, .unneeded, item, undefined) catch unreachable;
11244 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
11245 break :blk field_ty.zigTypeTag() != .NoReturn;
11257 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11258 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
1124611259 } else true;
1124711260
1124811261 if (emit_bb) sema.emitBackwardBranch(block, .unneeded) catch |err| switch (err) {
1124911262 error.NeededSourceLocation => {
1125011263 const case_src = Module.SwitchProngSrc{ .multi = .{ .prong = multi_i, .item = @intCast(u32, item_i) } };
11251 const decl = sema.mod.declPtr(case_block.src_decl);
11252 try sema.emitBackwardBranch(block, case_src.resolve(sema.gpa, decl, src_node_offset, .none));
11264 const decl = mod.declPtr(case_block.src_decl);
11265 try sema.emitBackwardBranch(block, case_src.resolve(mod, decl, src_node_offset, .none));
1125311266 unreachable;
1125411267 },
1125511268 else => return err,
......@@ -11285,8 +11298,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1128511298 for (items) |item_ref| {
1128611299 const item = try sema.resolveInst(item_ref);
1128711300 const item_val = sema.resolveConstValue(block, .unneeded, item, "") catch unreachable;
11288 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
11289 if (field_ty.zigTypeTag() != .NoReturn) break true;
11301 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11302 if (field_ty.zigTypeTag(mod) != .NoReturn) break true;
1129011303 } else false
1129111304 else
1129211305 true;
......@@ -11366,7 +11379,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1136611379 var cond_body = try case_block.instructions.toOwnedSlice(gpa);
1136711380 defer gpa.free(cond_body);
1136811381
11369 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope);
11382 var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope);
1137011383 defer wip_captures.deinit();
1137111384
1137211385 case_block.instructions.shrinkRetainingCapacity(0);
......@@ -11409,18 +11422,18 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1140911422 var final_else_body: []const Air.Inst.Index = &.{};
1141011423 if (special.body.len != 0 or !is_first or case_block.wantSafety()) {
1141111424 var emit_bb = false;
11412 if (special.is_inline) switch (operand_ty.zigTypeTag()) {
11425 if (special.is_inline) switch (operand_ty.zigTypeTag(mod)) {
1141311426 .Enum => {
11414 if (operand_ty.isNonexhaustiveEnum() and !union_originally) {
11427 if (operand_ty.isNonexhaustiveEnum(mod) and !union_originally) {
1141511428 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{
11416 operand_ty.fmt(sema.mod),
11429 operand_ty.fmt(mod),
1141711430 });
1141811431 }
1141911432 for (seen_enum_fields, 0..) |f, i| {
1142011433 if (f != null) continue;
1142111434 cases_len += 1;
1142211435
11423 const item_val = try Value.Tag.enum_field_index.create(sema.arena, @intCast(u32, i));
11436 const item_val = try mod.enumValueFieldIndex(operand_ty, @intCast(u32, i));
1142411437 const item_ref = try sema.addConstant(operand_ty, item_val);
1142511438 case_block.inline_case_capture = item_ref;
1142611439
......@@ -11428,8 +11441,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1142811441 case_block.wip_capture_scope = child_block.wip_capture_scope;
1142911442
1143011443 const analyze_body = if (union_originally) blk: {
11431 const field_ty = maybe_union_ty.unionFieldType(item_val, sema.mod);
11432 break :blk field_ty.zigTypeTag() != .NoReturn;
11444 const field_ty = maybe_union_ty.unionFieldType(item_val, mod);
11445 break :blk field_ty.zigTypeTag(mod) != .NoReturn;
1143311446 } else true;
1143411447
1143511448 if (emit_bb) try sema.emitBackwardBranch(block, special_prong_src);
......@@ -11449,17 +11462,21 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1144911462 }
1145011463 },
1145111464 .ErrorSet => {
11452 if (operand_ty.isAnyError()) {
11465 if (operand_ty.isAnyError(mod)) {
1145311466 return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{
11454 operand_ty.fmt(sema.mod),
11467 operand_ty.fmt(mod),
1145511468 });
1145611469 }
11457 for (operand_ty.errorSetNames()) |error_name| {
11470 for (0..operand_ty.errorSetNames(mod).len) |i| {
11471 const error_name = operand_ty.errorSetNames(mod)[i];
1145811472 if (seen_errors.contains(error_name)) continue;
1145911473 cases_len += 1;
1146011474
11461 const item_val = try Value.Tag.@"error".create(sema.arena, .{ .name = error_name });
11462 const item_ref = try sema.addConstant(operand_ty, item_val);
11475 const item_val = try mod.intern(.{ .err = .{
11476 .ty = operand_ty.toIntern(),
11477 .name = error_name,
11478 } });
11479 const item_ref = try sema.addConstant(operand_ty, item_val.toValue());
1146311480 case_block.inline_case_capture = item_ref;
1146411481
1146511482 case_block.instructions.shrinkRetainingCapacity(0);
......@@ -11482,7 +11499,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1148211499 while (try it.next()) |cur| {
1148311500 cases_len += 1;
1148411501
11485 const item_ref = try sema.addConstant(operand_ty, cur);
11502 const item_ref = try sema.addConstant(operand_ty, cur.toValue());
1148611503 case_block.inline_case_capture = item_ref;
1148711504
1148811505 case_block.instructions.shrinkRetainingCapacity(0);
......@@ -11539,19 +11556,19 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1153911556 }
1154011557 },
1154111558 else => return sema.fail(block, special_prong_src, "cannot enumerate values of type '{}' for 'inline else'", .{
11542 operand_ty.fmt(sema.mod),
11559 operand_ty.fmt(mod),
1154311560 }),
1154411561 };
1154511562
11546 var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, child_block.wip_capture_scope);
11563 var wip_captures = try WipCaptureScope.init(gpa, child_block.wip_capture_scope);
1154711564 defer wip_captures.deinit();
1154811565
1154911566 case_block.instructions.shrinkRetainingCapacity(0);
1155011567 case_block.wip_capture_scope = wip_captures.scope;
1155111568 case_block.inline_case_capture = .none;
1155211569
11553 if (sema.mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and
11554 operand_ty.zigTypeTag() == .Enum and (!operand_ty.isNonexhaustiveEnum() or union_originally))
11570 if (mod.backendSupportsFeature(.is_named_enum_value) and special.body.len != 0 and block.wantSafety() and
11571 operand_ty.zigTypeTag(mod) == .Enum and (!operand_ty.isNonexhaustiveEnum(mod) or union_originally))
1155511572 {
1155611573 try sema.zirDbgStmt(&case_block, cond_dbg_node_index);
1155711574 const ok = try case_block.addUnOp(.is_named_enum_value, operand);
......@@ -11561,9 +11578,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1156111578 const analyze_body = if (union_originally and !special.is_inline)
1156211579 for (seen_enum_fields, 0..) |seen_field, index| {
1156311580 if (seen_field != null) continue;
11564 const union_obj = maybe_union_ty.cast(Type.Payload.Union).?.data;
11581 const union_obj = mod.typeToUnion(maybe_union_ty).?;
1156511582 const field_ty = union_obj.fields.values()[index].ty;
11566 if (field_ty.zigTypeTag() != .NoReturn) break true;
11583 if (field_ty.zigTypeTag(mod) != .NoReturn) break true;
1156711584 } else false
1156811585 else
1156911586 true;
......@@ -11620,47 +11637,70 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1162011637}
1162111638
1162211639const RangeSetUnhandledIterator = struct {
11623 sema: *Sema,
11624 ty: Type,
11625 cur: Value,
11626 max: Value,
11640 mod: *Module,
11641 cur: ?InternPool.Index,
11642 max: InternPool.Index,
11643 range_i: usize,
1162711644 ranges: []const RangeSet.Range,
11628 range_i: usize = 0,
11629 first: bool = true,
11645 limbs: []math.big.Limb,
1163011646
11631 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
11632 const target = sema.mod.getTarget();
11633 const min = try ty.minInt(sema.arena, target);
11634 const max = try ty.maxInt(sema.arena, target);
11647 const preallocated_limbs = math.big.int.calcTwosCompLimbCount(128);
1163511648
11636 return RangeSetUnhandledIterator{
11637 .sema = sema,
11638 .ty = ty,
11639 .cur = min,
11640 .max = max,
11649 fn init(sema: *Sema, ty: Type, range_set: RangeSet) !RangeSetUnhandledIterator {
11650 const mod = sema.mod;
11651 const int_type = mod.intern_pool.indexToKey(ty.toIntern()).int_type;
11652 const needed_limbs = math.big.int.calcTwosCompLimbCount(int_type.bits);
11653 return .{
11654 .mod = mod,
11655 .cur = (try ty.minInt(mod, ty)).toIntern(),
11656 .max = (try ty.maxInt(mod, ty)).toIntern(),
11657 .range_i = 0,
1164111658 .ranges = range_set.ranges.items,
11659 .limbs = if (needed_limbs > preallocated_limbs)
11660 try sema.arena.alloc(math.big.Limb, needed_limbs)
11661 else
11662 &.{},
1164211663 };
1164311664 }
1164411665
11645 fn next(it: *RangeSetUnhandledIterator) !?Value {
11646 while (it.range_i < it.ranges.len) : (it.range_i += 1) {
11647 if (!it.first) {
11648 it.cur = try it.sema.intAdd(it.cur, Value.one, it.ty);
11649 }
11650 it.first = false;
11651 if (it.cur.compareAll(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {
11652 return it.cur;
11653 }
11654 it.cur = it.ranges[it.range_i].last;
11655 }
11656 if (!it.first) {
11657 it.cur = try it.sema.intAdd(it.cur, Value.one, it.ty);
11666 fn addOne(it: *const RangeSetUnhandledIterator, val: InternPool.Index) !?InternPool.Index {
11667 if (val == it.max) return null;
11668 const int = it.mod.intern_pool.indexToKey(val).int;
11669
11670 switch (int.storage) {
11671 inline .u64, .i64 => |val_int| {
11672 const next_int = @addWithOverflow(val_int, 1);
11673 if (next_int[1] == 0)
11674 return (try it.mod.intValue(int.ty.toType(), next_int[0])).toIntern();
11675 },
11676 .big_int => {},
11677 .lazy_align, .lazy_size => unreachable,
1165811678 }
11659 it.first = false;
11660 if (it.cur.compareAll(.lte, it.max, it.ty, it.sema.mod)) {
11661 return it.cur;
11679
11680 var val_space: InternPool.Key.Int.Storage.BigIntSpace = undefined;
11681 const val_bigint = int.storage.toBigInt(&val_space);
11682
11683 var result_limbs: [preallocated_limbs]math.big.Limb = undefined;
11684 var result_bigint = math.big.int.Mutable.init(
11685 if (it.limbs.len > 0) it.limbs else &result_limbs,
11686 0,
11687 );
11688
11689 result_bigint.addScalar(val_bigint, 1);
11690 return (try it.mod.intValue_big(int.ty.toType(), result_bigint.toConst())).toIntern();
11691 }
11692
11693 fn next(it: *RangeSetUnhandledIterator) !?InternPool.Index {
11694 var cur = it.cur orelse return null;
11695 while (it.range_i < it.ranges.len and cur == it.ranges[it.range_i].first) {
11696 defer it.range_i += 1;
11697 cur = (try it.addOne(it.ranges[it.range_i].last)) orelse {
11698 it.cur = null;
11699 return null;
11700 };
1166211701 }
11663 return null;
11702 it.cur = try it.addOne(cur);
11703 return cur;
1166411704 }
1166511705};
1166611706
......@@ -11671,18 +11711,17 @@ fn resolveSwitchItemVal(
1167111711 switch_node_offset: i32,
1167211712 switch_prong_src: Module.SwitchProngSrc,
1167311713 range_expand: Module.SwitchProngSrc.RangeExpand,
11674) CompileError!TypedValue {
11714) CompileError!InternPool.Index {
11715 const mod = sema.mod;
1167511716 const item = try sema.resolveInst(item_ref);
11676 const item_ty = sema.typeOf(item);
1167711717 // Constructing a LazySrcLoc is costly because we only have the switch AST node.
1167811718 // Only if we know for sure we need to report a compile error do we resolve the
1167911719 // full source locations.
11680 if (sema.resolveConstValue(block, .unneeded, item, "")) |val| {
11681 try sema.resolveLazyValue(val);
11682 return TypedValue{ .ty = item_ty, .val = val };
11720 if (sema.resolveConstLazyValue(block, .unneeded, item, "")) |val| {
11721 return val.toIntern();
1168311722 } else |err| switch (err) {
1168411723 error.NeededSourceLocation => {
11685 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), switch_node_offset, range_expand);
11724 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), switch_node_offset, range_expand);
1168611725 _ = try sema.resolveConstValue(block, src, item, "switch prong values must be comptime-known");
1168711726 unreachable;
1168811727 },
......@@ -11696,17 +11735,17 @@ fn validateSwitchRange(
1169611735 range_set: *RangeSet,
1169711736 first_ref: Zir.Inst.Ref,
1169811737 last_ref: Zir.Inst.Ref,
11699 operand_ty: Type,
1170011738 src_node_offset: i32,
1170111739 switch_prong_src: Module.SwitchProngSrc,
1170211740) CompileError!void {
11703 const first_val = (try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first)).val;
11704 const last_val = (try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last)).val;
11705 if (first_val.compareAll(.gt, last_val, operand_ty, sema.mod)) {
11706 const src = switch_prong_src.resolve(sema.gpa, sema.mod.declPtr(block.src_decl), src_node_offset, .first);
11741 const mod = sema.mod;
11742 const first = try sema.resolveSwitchItemVal(block, first_ref, src_node_offset, switch_prong_src, .first);
11743 const last = try sema.resolveSwitchItemVal(block, last_ref, src_node_offset, switch_prong_src, .last);
11744 if (first.toValue().compareScalar(.gt, last.toValue(), mod.intern_pool.typeOf(first).toType(), mod)) {
11745 const src = switch_prong_src.resolve(mod, mod.declPtr(block.src_decl), src_node_offset, .first);
1170711746 return sema.fail(block, src, "range start value is greater than the end value", .{});
1170811747 }
11709 const maybe_prev_src = try range_set.add(first_val, last_val, operand_ty, switch_prong_src);
11748 const maybe_prev_src = try range_set.add(first, last, switch_prong_src);
1171011749 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1171111750}
1171211751
......@@ -11715,12 +11754,11 @@ fn validateSwitchItem(
1171511754 block: *Block,
1171611755 range_set: *RangeSet,
1171711756 item_ref: Zir.Inst.Ref,
11718 operand_ty: Type,
1171911757 src_node_offset: i32,
1172011758 switch_prong_src: Module.SwitchProngSrc,
1172111759) CompileError!void {
11722 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
11723 const maybe_prev_src = try range_set.add(item_val, item_val, operand_ty, switch_prong_src);
11760 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11761 const maybe_prev_src = try range_set.add(item, item, switch_prong_src);
1172411762 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1172511763}
1172611764
......@@ -11733,9 +11771,11 @@ fn validateSwitchItemEnum(
1173311771 src_node_offset: i32,
1173411772 switch_prong_src: Module.SwitchProngSrc,
1173511773) CompileError!void {
11736 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11737 const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val, sema.mod) orelse {
11738 const maybe_prev_src = try range_set.add(item_tv.val, item_tv.val, item_tv.ty, switch_prong_src);
11774 const ip = &sema.mod.intern_pool;
11775 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11776 const int = ip.indexToKey(item).enum_tag.int;
11777 const field_index = ip.indexToKey(ip.typeOf(item)).enum_type.tagValueIndex(ip, int) orelse {
11778 const maybe_prev_src = try range_set.add(int, int, switch_prong_src);
1173911779 return sema.validateSwitchDupe(block, maybe_prev_src, switch_prong_src, src_node_offset);
1174011780 };
1174111781 const maybe_prev_src = seen_fields[field_index];
......@@ -11751,9 +11791,10 @@ fn validateSwitchItemError(
1175111791 src_node_offset: i32,
1175211792 switch_prong_src: Module.SwitchProngSrc,
1175311793) CompileError!void {
11754 const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11794 const ip = &sema.mod.intern_pool;
11795 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
1175511796 // TODO: Do i need to typecheck here?
11756 const error_name = item_tv.val.castTag(.@"error").?.data.name;
11797 const error_name = ip.indexToKey(item).err.name;
1175711798 const maybe_prev_src = if (try seen_errors.fetchPut(error_name, switch_prong_src)) |prev|
1175811799 prev.value
1175911800 else
......@@ -11769,10 +11810,10 @@ fn validateSwitchDupe(
1176911810 src_node_offset: i32,
1177011811) CompileError!void {
1177111812 const prev_prong_src = maybe_prev_src orelse return;
11772 const gpa = sema.gpa;
11773 const block_src_decl = sema.mod.declPtr(block.src_decl);
11774 const src = switch_prong_src.resolve(gpa, block_src_decl, src_node_offset, .none);
11775 const prev_src = prev_prong_src.resolve(gpa, block_src_decl, src_node_offset, .none);
11813 const mod = sema.mod;
11814 const block_src_decl = mod.declPtr(block.src_decl);
11815 const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none);
11816 const prev_src = prev_prong_src.resolve(mod, block_src_decl, src_node_offset, .none);
1177611817 const msg = msg: {
1177711818 const msg = try sema.errMsg(
1177811819 block,
......@@ -11802,20 +11843,21 @@ fn validateSwitchItemBool(
1180211843 src_node_offset: i32,
1180311844 switch_prong_src: Module.SwitchProngSrc,
1180411845) CompileError!void {
11805 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
11806 if (item_val.toBool()) {
11846 const mod = sema.mod;
11847 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11848 if (item.toValue().toBool()) {
1180711849 true_count.* += 1;
1180811850 } else {
1180911851 false_count.* += 1;
1181011852 }
1181111853 if (true_count.* + false_count.* > 2) {
11812 const block_src_decl = sema.mod.declPtr(block.src_decl);
11813 const src = switch_prong_src.resolve(sema.gpa, block_src_decl, src_node_offset, .none);
11854 const block_src_decl = mod.declPtr(block.src_decl);
11855 const src = switch_prong_src.resolve(mod, block_src_decl, src_node_offset, .none);
1181411856 return sema.fail(block, src, "duplicate switch value", .{});
1181511857 }
1181611858}
1181711859
11818const ValueSrcMap = std.HashMap(Value, Module.SwitchProngSrc, Value.HashContext, std.hash_map.default_max_load_percentage);
11860const ValueSrcMap = std.AutoHashMapUnmanaged(InternPool.Index, Module.SwitchProngSrc);
1181911861
1182011862fn validateSwitchItemSparse(
1182111863 sema: *Sema,
......@@ -11825,8 +11867,8 @@ fn validateSwitchItemSparse(
1182511867 src_node_offset: i32,
1182611868 switch_prong_src: Module.SwitchProngSrc,
1182711869) CompileError!void {
11828 const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val;
11829 const kv = (try seen_values.fetchPut(item_val, switch_prong_src)) orelse return;
11870 const item = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none);
11871 const kv = (try seen_values.fetchPut(sema.gpa, item, switch_prong_src)) orelse return;
1183011872 return sema.validateSwitchDupe(block, kv.value, switch_prong_src, src_node_offset);
1183111873}
1183211874
......@@ -11864,7 +11906,8 @@ fn validateSwitchNoRange(
1186411906}
1186511907
1186611908fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, operand: Air.Inst.Ref) !bool {
11867 if (!sema.mod.backendSupportsFeature(.panic_unwrap_error)) return false;
11909 const mod = sema.mod;
11910 if (!mod.backendSupportsFeature(.panic_unwrap_error)) return false;
1186811911
1186911912 const tags = sema.code.instructions.items(.tag);
1187011913 for (body) |inst| {
......@@ -11900,7 +11943,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1190011943 .as_node => try sema.zirAsNode(block, inst),
1190111944 .field_val => try sema.zirFieldVal(block, inst),
1190211945 .@"unreachable" => {
11903 if (!sema.mod.comp.formatted_panics) {
11946 if (!mod.comp.formatted_panics) {
1190411947 try sema.safetyPanic(block, .unwrap_error);
1190511948 return true;
1190611949 }
......@@ -11923,7 +11966,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1192311966 },
1192411967 else => unreachable,
1192511968 };
11926 if (sema.typeOf(air_inst).isNoReturn())
11969 if (sema.typeOf(air_inst).isNoReturn(mod))
1192711970 return true;
1192811971 sema.inst_map.putAssumeCapacity(inst, air_inst);
1192911972 }
......@@ -11931,19 +11974,20 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
1193111974}
1193211975
1193311976fn maybeErrorUnwrapCondbr(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, cond: Zir.Inst.Ref, cond_src: LazySrcLoc) !void {
11977 const mod = sema.mod;
1193411978 const index = Zir.refToIndex(cond) orelse return;
1193511979 if (sema.code.instructions.items(.tag)[index] != .is_non_err) return;
1193611980
1193711981 const err_inst_data = sema.code.instructions.items(.data)[index].un_node;
1193811982 const err_operand = try sema.resolveInst(err_inst_data.operand);
1193911983 const operand_ty = sema.typeOf(err_operand);
11940 if (operand_ty.zigTypeTag() == .ErrorSet) {
11984 if (operand_ty.zigTypeTag(mod) == .ErrorSet) {
1194111985 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
1194211986 return;
1194311987 }
1194411988 if (try sema.resolveDefinedValue(block, cond_src, err_operand)) |val| {
11945 if (!operand_ty.isError()) return;
11946 if (val.getError() == null) return;
11989 if (!operand_ty.isError(mod)) return;
11990 if (val.getErrorName(mod) == .none) return;
1194711991 try sema.maybeErrorUnwrapComptime(block, body, err_operand);
1194811992 }
1194911993}
......@@ -11965,45 +12009,60 @@ fn maybeErrorUnwrapComptime(sema: *Sema, block: *Block, body: []const Zir.Inst.I
1196512009 const src = inst_data.src();
1196612010
1196712011 if (try sema.resolveDefinedValue(block, src, operand)) |val| {
11968 if (val.getError()) |name| {
11969 return sema.fail(block, src, "caught unexpected error '{s}'", .{name});
12012 if (val.getErrorName(sema.mod).unwrap()) |name| {
12013 return sema.fail(block, src, "caught unexpected error '{}'", .{name.fmt(&sema.mod.intern_pool)});
1197012014 }
1197112015 }
1197212016}
1197312017
1197412018fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12019 const mod = sema.mod;
1197512020 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1197612021 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1197712022 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1197812023 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1197912024 const unresolved_ty = try sema.resolveType(block, ty_src, extra.lhs);
11980 const field_name = try sema.resolveConstString(block, name_src, extra.rhs, "field name must be comptime-known");
12025 const field_name = try sema.resolveConstStringIntern(block, name_src, extra.rhs, "field name must be comptime-known");
1198112026 const ty = try sema.resolveTypeFields(unresolved_ty);
12027 const ip = &mod.intern_pool;
1198212028
1198312029 const has_field = hf: {
11984 if (ty.isSlice()) {
11985 if (mem.eql(u8, field_name, "ptr")) break :hf true;
11986 if (mem.eql(u8, field_name, "len")) break :hf true;
11987 break :hf false;
11988 }
11989 if (ty.castTag(.anon_struct)) |pl| {
11990 break :hf for (pl.data.names) |name| {
11991 if (mem.eql(u8, name, field_name)) break true;
11992 } else false;
11993 }
11994 if (ty.isTuple()) {
11995 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch break :hf false;
11996 break :hf field_index < ty.structFieldCount();
11997 }
11998 break :hf switch (ty.zigTypeTag()) {
11999 .Struct => ty.structFields().contains(field_name),
12000 .Union => ty.unionFields().contains(field_name),
12001 .Enum => ty.enumFields().contains(field_name),
12002 .Array => mem.eql(u8, field_name, "len"),
12003 else => return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
12004 ty.fmt(sema.mod),
12005 }),
12006 };
12030 switch (ip.indexToKey(ty.toIntern())) {
12031 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
12032 .Slice => {
12033 if (ip.stringEqlSlice(field_name, "ptr")) break :hf true;
12034 if (ip.stringEqlSlice(field_name, "len")) break :hf true;
12035 break :hf false;
12036 },
12037 else => {},
12038 },
12039 .anon_struct_type => |anon_struct| {
12040 if (anon_struct.names.len != 0) {
12041 break :hf mem.indexOfScalar(InternPool.NullTerminatedString, anon_struct.names, field_name) != null;
12042 } else {
12043 const field_index = field_name.toUnsigned(ip) orelse break :hf false;
12044 break :hf field_index < ty.structFieldCount(mod);
12045 }
12046 },
12047 .struct_type => |struct_type| {
12048 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :hf false;
12049 assert(struct_obj.haveFieldTypes());
12050 break :hf struct_obj.fields.contains(field_name);
12051 },
12052 .union_type => |union_type| {
12053 const union_obj = mod.unionPtr(union_type.index);
12054 assert(union_obj.haveFieldTypes());
12055 break :hf union_obj.fields.contains(field_name);
12056 },
12057 .enum_type => |enum_type| {
12058 break :hf enum_type.nameIndex(ip, field_name) != null;
12059 },
12060 .array_type => break :hf ip.stringEqlSlice(field_name, "len"),
12061 else => {},
12062 }
12063 return sema.fail(block, ty_src, "type '{}' does not support '@hasField'", .{
12064 ty.fmt(mod),
12065 });
1200712066 };
1200812067 if (has_field) {
1200912068 return Air.Inst.Ref.bool_true;
......@@ -12013,20 +12072,22 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1201312072}
1201412073
1201512074fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12075 const mod = sema.mod;
1201612076 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1201712077 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1201812078 const src = inst_data.src();
1201912079 const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1202012080 const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1202112081 const container_type = try sema.resolveType(block, lhs_src, extra.lhs);
12022 const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs, "decl name must be comptime-known");
12082 const decl_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, "decl name must be comptime-known");
1202312083
1202412084 try sema.checkNamespaceType(block, lhs_src, container_type);
1202512085
12026 const namespace = container_type.getNamespace() orelse return Air.Inst.Ref.bool_false;
12086 const namespace = container_type.getNamespaceIndex(mod).unwrap() orelse
12087 return Air.Inst.Ref.bool_false;
1202712088 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| {
12028 const decl = sema.mod.declPtr(decl_index);
12029 if (decl.is_pub or decl.getFileScope() == block.getFileScope()) {
12089 const decl = mod.declPtr(decl_index);
12090 if (decl.is_pub or decl.getFileScope(mod) == block.getFileScope(mod)) {
1203012091 return Air.Inst.Ref.bool_true;
1203112092 }
1203212093 }
......@@ -12042,12 +12103,12 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1204212103 const operand_src = inst_data.src();
1204312104 const operand = inst_data.get(sema.code);
1204412105
12045 const result = mod.importFile(block.getFileScope(), operand) catch |err| switch (err) {
12106 const result = mod.importFile(block.getFileScope(mod), operand) catch |err| switch (err) {
1204612107 error.ImportOutsidePkgPath => {
1204712108 return sema.fail(block, operand_src, "import of file outside package path: '{s}'", .{operand});
1204812109 },
1204912110 error.PackageNotFound => {
12050 const name = try block.getFileScope().pkg.getName(sema.gpa, mod.*);
12111 const name = try block.getFileScope(mod).pkg.getName(sema.gpa, mod.*);
1205112112 defer sema.gpa.free(name);
1205212113 return sema.fail(block, operand_src, "no package named '{s}' available within package '{s}'", .{ operand, name });
1205312114 },
......@@ -12073,7 +12134,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1207312134 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1207412135 const name = try sema.resolveConstString(block, operand_src, inst_data.operand, "file path name must be comptime-known");
1207512136
12076 const embed_file = mod.embedFile(block.getFileScope(), name) catch |err| switch (err) {
12137 const embed_file = mod.embedFile(block.getFileScope(mod), name) catch |err| switch (err) {
1207712138 error.ImportOutsidePkgPath => {
1207812139 return sema.fail(block, operand_src, "embed of file outside package path: '{s}'", .{name});
1207912140 },
......@@ -12087,17 +12148,23 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1208712148 var anon_decl = try block.startAnonDecl();
1208812149 defer anon_decl.deinit();
1208912150
12090 const bytes_including_null = embed_file.bytes[0 .. embed_file.bytes.len + 1];
12091
12092 // TODO instead of using `Value.Tag.bytes`, create a new value tag for pointing at
12151 // TODO instead of using `.bytes`, create a new value tag for pointing at
1209312152 // a `*Module.EmbedFile`. The purpose of this would be:
1209412153 // - If only the length is read and the bytes are not inspected by comptime code,
1209512154 // there can be an optimization where the codegen backend does a copy_file_range
1209612155 // into the final binary, and never loads the data into memory.
1209712156 // - When a Decl is destroyed, it can free the `*Module.EmbedFile`.
12157 const ty = try mod.arrayType(.{
12158 .len = embed_file.bytes.len,
12159 .child = .u8_type,
12160 .sentinel = .zero_u8,
12161 });
1209812162 embed_file.owner_decl = try anon_decl.finish(
12099 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), embed_file.bytes.len),
12100 try Value.Tag.bytes.create(anon_decl.arena(), bytes_including_null),
12163 ty,
12164 (try mod.intern(.{ .aggregate = .{
12165 .ty = ty.toIntern(),
12166 .storage = .{ .bytes = embed_file.bytes },
12167 } })).toValue(),
1210112168 0, // default alignment
1210212169 );
1210312170
......@@ -12105,16 +12172,15 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1210512172}
1210612173
1210712174fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
12175 const mod = sema.mod;
1210812176 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
12109 const err_name = inst_data.get(sema.code);
12110
12111 // Return the error code from the function.
12112 const kv = try sema.mod.getErrorValue(err_name);
12113 const result_inst = try sema.addConstant(
12114 try Type.Tag.error_set_single.create(sema.arena, kv.key),
12115 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),
12116 );
12117 return result_inst;
12177 const name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
12178 _ = try mod.getErrorValue(name);
12179 const error_set_type = try mod.singleErrorSetType(name);
12180 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
12181 .ty = error_set_type.toIntern(),
12182 .name = name,
12183 } })).toValue());
1211812184}
1211912185
1212012186fn zirShl(
......@@ -12126,6 +12192,7 @@ fn zirShl(
1212612192 const tracy = trace(@src());
1212712193 defer tracy.end();
1212812194
12195 const mod = sema.mod;
1212912196 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1213012197 const src = inst_data.src();
1213112198 sema.src = src;
......@@ -12136,11 +12203,10 @@ fn zirShl(
1213612203 const rhs = try sema.resolveInst(extra.rhs);
1213712204 const lhs_ty = sema.typeOf(lhs);
1213812205 const rhs_ty = sema.typeOf(rhs);
12139 const target = sema.mod.getTarget();
1214012206 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1214112207
12142 const scalar_ty = lhs_ty.scalarType();
12143 const scalar_rhs_ty = rhs_ty.scalarType();
12208 const scalar_ty = lhs_ty.scalarType(mod);
12209 const scalar_rhs_ty = rhs_ty.scalarType(mod);
1214412210
1214512211 // TODO coerce rhs if air_tag is not shl_sat
1214612212 const rhs_is_comptime_int = try sema.checkIntType(block, rhs_src, scalar_rhs_ty);
......@@ -12149,62 +12215,56 @@ fn zirShl(
1214912215 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);
1215012216
1215112217 if (maybe_rhs_val) |rhs_val| {
12152 if (rhs_val.isUndef()) {
12218 if (rhs_val.isUndef(mod)) {
1215312219 return sema.addConstUndef(sema.typeOf(lhs));
1215412220 }
1215512221 // If rhs is 0, return lhs without doing any calculations.
1215612222 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
1215712223 return lhs;
1215812224 }
12159 if (scalar_ty.zigTypeTag() != .ComptimeInt and air_tag != .shl_sat) {
12160 var bits_payload = Value.Payload.U64{
12161 .base = .{ .tag = .int_u64 },
12162 .data = scalar_ty.intInfo(target).bits,
12163 };
12164 const bit_value = Value.initPayload(&bits_payload.base);
12165 if (rhs_ty.zigTypeTag() == .Vector) {
12225 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt and air_tag != .shl_sat) {
12226 const bit_value = try mod.intValue(Type.comptime_int, scalar_ty.intInfo(mod).bits);
12227 if (rhs_ty.zigTypeTag(mod) == .Vector) {
1216612228 var i: usize = 0;
12167 while (i < rhs_ty.vectorLen()) : (i += 1) {
12168 var elem_value_buf: Value.ElemValueBuffer = undefined;
12169 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);
12170 if (rhs_elem.compareHetero(.gte, bit_value, target)) {
12229 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12230 const rhs_elem = try rhs_val.elemValue(mod, i);
12231 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {
1217112232 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{
12172 rhs_elem.fmtValue(scalar_ty, sema.mod),
12233 rhs_elem.fmtValue(scalar_ty, mod),
1217312234 i,
12174 scalar_ty.fmt(sema.mod),
12235 scalar_ty.fmt(mod),
1217512236 });
1217612237 }
1217712238 }
12178 } else if (rhs_val.compareHetero(.gte, bit_value, target)) {
12239 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {
1217912240 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
12180 rhs_val.fmtValue(scalar_ty, sema.mod),
12181 scalar_ty.fmt(sema.mod),
12241 rhs_val.fmtValue(scalar_ty, mod),
12242 scalar_ty.fmt(mod),
1218212243 });
1218312244 }
1218412245 }
12185 if (rhs_ty.zigTypeTag() == .Vector) {
12246 if (rhs_ty.zigTypeTag(mod) == .Vector) {
1218612247 var i: usize = 0;
12187 while (i < rhs_ty.vectorLen()) : (i += 1) {
12188 var elem_value_buf: Value.ElemValueBuffer = undefined;
12189 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);
12190 if (rhs_elem.compareHetero(.lt, Value.zero, target)) {
12248 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12249 const rhs_elem = try rhs_val.elemValue(mod, i);
12250 if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) {
1219112251 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
12192 rhs_elem.fmtValue(scalar_ty, sema.mod),
12252 rhs_elem.fmtValue(scalar_ty, mod),
1219312253 i,
1219412254 });
1219512255 }
1219612256 }
12197 } else if (rhs_val.compareHetero(.lt, Value.zero, target)) {
12257 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
1219812258 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
12199 rhs_val.fmtValue(scalar_ty, sema.mod),
12259 rhs_val.fmtValue(scalar_ty, mod),
1220012260 });
1220112261 }
1220212262 }
1220312263
1220412264 const runtime_src = if (maybe_lhs_val) |lhs_val| rs: {
12205 if (lhs_val.isUndef()) return sema.addConstUndef(lhs_ty);
12265 if (lhs_val.isUndef(mod)) return sema.addConstUndef(lhs_ty);
1220612266 const rhs_val = maybe_rhs_val orelse {
12207 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
12267 if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) {
1220812268 return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{});
1220912269 }
1221012270 break :rs rhs_src;
......@@ -12212,25 +12272,25 @@ fn zirShl(
1221212272
1221312273 const val = switch (air_tag) {
1221412274 .shl_exact => val: {
12215 const shifted = try lhs_val.shlWithOverflow(rhs_val, lhs_ty, sema.arena, sema.mod);
12216 if (scalar_ty.zigTypeTag() == .ComptimeInt) {
12275 const shifted = try lhs_val.shlWithOverflow(rhs_val, lhs_ty, sema.arena, mod);
12276 if (scalar_ty.zigTypeTag(mod) == .ComptimeInt) {
1221712277 break :val shifted.wrapped_result;
1221812278 }
12219 if (shifted.overflow_bit.compareAllWithZero(.eq, sema.mod)) {
12279 if (shifted.overflow_bit.compareAllWithZero(.eq, mod)) {
1222012280 break :val shifted.wrapped_result;
1222112281 }
1222212282 return sema.fail(block, src, "operation caused overflow", .{});
1222312283 },
1222412284
12225 .shl_sat => if (scalar_ty.zigTypeTag() == .ComptimeInt)
12226 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod)
12285 .shl_sat => if (scalar_ty.zigTypeTag(mod) == .ComptimeInt)
12286 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, mod)
1222712287 else
12228 try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, sema.mod),
12288 try lhs_val.shlSat(rhs_val, lhs_ty, sema.arena, mod),
1222912289
12230 .shl => if (scalar_ty.zigTypeTag() == .ComptimeInt)
12231 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, sema.mod)
12290 .shl => if (scalar_ty.zigTypeTag(mod) == .ComptimeInt)
12291 try lhs_val.shl(rhs_val, lhs_ty, sema.arena, mod)
1223212292 else
12233 try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, sema.mod),
12293 try lhs_val.shlTrunc(rhs_val, lhs_ty, sema.arena, mod),
1223412294
1223512295 else => unreachable,
1223612296 };
......@@ -12241,11 +12301,11 @@ fn zirShl(
1224112301 const new_rhs = if (air_tag == .shl_sat) rhs: {
1224212302 // Limit the RHS type for saturating shl to be an integer as small as the LHS.
1224312303 if (rhs_is_comptime_int or
12244 scalar_rhs_ty.intInfo(target).bits > scalar_ty.intInfo(target).bits)
12304 scalar_rhs_ty.intInfo(mod).bits > scalar_ty.intInfo(mod).bits)
1224512305 {
1224612306 const max_int = try sema.addConstant(
1224712307 lhs_ty,
12248 try lhs_ty.maxInt(sema.arena, target),
12308 try lhs_ty.maxInt(mod, lhs_ty),
1224912309 );
1225012310 const rhs_limited = try sema.analyzeMinMax(block, rhs_src, .min, &.{ rhs, max_int }, &.{ rhs_src, rhs_src });
1225112311 break :rhs try sema.intCast(block, src, lhs_ty, rhs_src, rhs_limited, rhs_src, false);
......@@ -12256,12 +12316,11 @@ fn zirShl(
1225612316
1225712317 try sema.requireRuntimeBlock(block, src, runtime_src);
1225812318 if (block.wantSafety()) {
12259 const bit_count = scalar_ty.intInfo(target).bits;
12319 const bit_count = scalar_ty.intInfo(mod).bits;
1226012320 if (!std.math.isPowerOfTwo(bit_count)) {
12261 const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count);
12262
12263 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
12264 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12321 const bit_count_val = try mod.intValue(scalar_rhs_ty, bit_count);
12322 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
12323 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
1226512324 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
1226612325 break :ok try block.addInst(.{
1226712326 .tag = .reduce,
......@@ -12290,7 +12349,7 @@ fn zirShl(
1229012349 } },
1229112350 });
1229212351 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
12293 const any_ov_bit = if (lhs_ty.zigTypeTag() == .Vector)
12352 const any_ov_bit = if (lhs_ty.zigTypeTag(mod) == .Vector)
1229412353 try block.addInst(.{
1229512354 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1229612355 .data = .{ .reduce = .{
......@@ -12300,7 +12359,7 @@ fn zirShl(
1230012359 })
1230112360 else
1230212361 ov_bit;
12303 const zero_ov = try sema.addConstant(Type.u1, Value.zero);
12362 const zero_ov = try sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
1230412363 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
1230512364
1230612365 try sema.addSafetyCheck(block, no_ov, .shl_overflow);
......@@ -12319,6 +12378,7 @@ fn zirShr(
1231912378 const tracy = trace(@src());
1232012379 defer tracy.end();
1232112380
12381 const mod = sema.mod;
1232212382 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1232312383 const src = inst_data.src();
1232412384 sema.src = src;
......@@ -12330,94 +12390,87 @@ fn zirShr(
1233012390 const lhs_ty = sema.typeOf(lhs);
1233112391 const rhs_ty = sema.typeOf(rhs);
1233212392 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
12333 const target = sema.mod.getTarget();
12334 const scalar_ty = lhs_ty.scalarType();
12393 const scalar_ty = lhs_ty.scalarType(mod);
1233512394
1233612395 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(lhs);
1233712396 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(rhs);
1233812397
1233912398 const runtime_src = if (maybe_rhs_val) |rhs_val| rs: {
12340 if (rhs_val.isUndef()) {
12399 if (rhs_val.isUndef(mod)) {
1234112400 return sema.addConstUndef(lhs_ty);
1234212401 }
1234312402 // If rhs is 0, return lhs without doing any calculations.
1234412403 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
1234512404 return lhs;
1234612405 }
12347 if (scalar_ty.zigTypeTag() != .ComptimeInt) {
12348 var bits_payload = Value.Payload.U64{
12349 .base = .{ .tag = .int_u64 },
12350 .data = scalar_ty.intInfo(target).bits,
12351 };
12352 const bit_value = Value.initPayload(&bits_payload.base);
12353 if (rhs_ty.zigTypeTag() == .Vector) {
12406 if (scalar_ty.zigTypeTag(mod) != .ComptimeInt) {
12407 const bit_value = try mod.intValue(Type.comptime_int, scalar_ty.intInfo(mod).bits);
12408 if (rhs_ty.zigTypeTag(mod) == .Vector) {
1235412409 var i: usize = 0;
12355 while (i < rhs_ty.vectorLen()) : (i += 1) {
12356 var elem_value_buf: Value.ElemValueBuffer = undefined;
12357 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);
12358 if (rhs_elem.compareHetero(.gte, bit_value, target)) {
12410 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12411 const rhs_elem = try rhs_val.elemValue(mod, i);
12412 if (rhs_elem.compareHetero(.gte, bit_value, mod)) {
1235912413 return sema.fail(block, rhs_src, "shift amount '{}' at index '{d}' is too large for operand type '{}'", .{
12360 rhs_elem.fmtValue(scalar_ty, sema.mod),
12414 rhs_elem.fmtValue(scalar_ty, mod),
1236112415 i,
12362 scalar_ty.fmt(sema.mod),
12416 scalar_ty.fmt(mod),
1236312417 });
1236412418 }
1236512419 }
12366 } else if (rhs_val.compareHetero(.gte, bit_value, target)) {
12420 } else if (rhs_val.compareHetero(.gte, bit_value, mod)) {
1236712421 return sema.fail(block, rhs_src, "shift amount '{}' is too large for operand type '{}'", .{
12368 rhs_val.fmtValue(scalar_ty, sema.mod),
12369 scalar_ty.fmt(sema.mod),
12422 rhs_val.fmtValue(scalar_ty, mod),
12423 scalar_ty.fmt(mod),
1237012424 });
1237112425 }
1237212426 }
12373 if (rhs_ty.zigTypeTag() == .Vector) {
12427 if (rhs_ty.zigTypeTag(mod) == .Vector) {
1237412428 var i: usize = 0;
12375 while (i < rhs_ty.vectorLen()) : (i += 1) {
12376 var elem_value_buf: Value.ElemValueBuffer = undefined;
12377 const rhs_elem = rhs_val.elemValueBuffer(sema.mod, i, &elem_value_buf);
12378 if (rhs_elem.compareHetero(.lt, Value.zero, target)) {
12429 while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
12430 const rhs_elem = try rhs_val.elemValue(mod, i);
12431 if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) {
1237912432 return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
12380 rhs_elem.fmtValue(scalar_ty, sema.mod),
12433 rhs_elem.fmtValue(scalar_ty, mod),
1238112434 i,
1238212435 });
1238312436 }
1238412437 }
12385 } else if (rhs_val.compareHetero(.lt, Value.zero, target)) {
12438 } else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
1238612439 return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
12387 rhs_val.fmtValue(scalar_ty, sema.mod),
12440 rhs_val.fmtValue(scalar_ty, mod),
1238812441 });
1238912442 }
1239012443 if (maybe_lhs_val) |lhs_val| {
12391 if (lhs_val.isUndef()) {
12444 if (lhs_val.isUndef(mod)) {
1239212445 return sema.addConstUndef(lhs_ty);
1239312446 }
1239412447 if (air_tag == .shr_exact) {
1239512448 // Detect if any ones would be shifted out.
12396 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, sema.mod);
12449 const truncated = try lhs_val.intTruncBitsAsValue(lhs_ty, sema.arena, .unsigned, rhs_val, mod);
1239712450 if (!(try truncated.compareAllWithZeroAdvanced(.eq, sema))) {
1239812451 return sema.fail(block, src, "exact shift shifted out 1 bits", .{});
1239912452 }
1240012453 }
12401 const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena, sema.mod);
12454 const val = try lhs_val.shr(rhs_val, lhs_ty, sema.arena, mod);
1240212455 return sema.addConstant(lhs_ty, val);
1240312456 } else {
1240412457 break :rs lhs_src;
1240512458 }
1240612459 } else rhs_src;
1240712460
12408 if (maybe_rhs_val == null and scalar_ty.zigTypeTag() == .ComptimeInt) {
12461 if (maybe_rhs_val == null and scalar_ty.zigTypeTag(mod) == .ComptimeInt) {
1240912462 return sema.fail(block, src, "LHS of shift must be a fixed-width integer type, or RHS must be comptime-known", .{});
1241012463 }
1241112464
1241212465 try sema.requireRuntimeBlock(block, src, runtime_src);
1241312466 const result = try block.addBinOp(air_tag, lhs, rhs);
1241412467 if (block.wantSafety()) {
12415 const bit_count = scalar_ty.intInfo(target).bits;
12468 const bit_count = scalar_ty.intInfo(mod).bits;
1241612469 if (!std.math.isPowerOfTwo(bit_count)) {
12417 const bit_count_val = try Value.Tag.int_u64.create(sema.arena, bit_count);
12470 const bit_count_val = try mod.intValue(rhs_ty.scalarType(mod), bit_count);
1241812471
12419 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
12420 const bit_count_inst = try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, bit_count_val));
12472 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
12473 const bit_count_inst = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, bit_count_val));
1242112474 const lt = try block.addCmpVector(rhs, bit_count_inst, .lt);
1242212475 break :ok try block.addInst(.{
1242312476 .tag = .reduce,
......@@ -12436,7 +12489,7 @@ fn zirShr(
1243612489 if (air_tag == .shr_exact) {
1243712490 const back = try block.addBinOp(.shl, result, rhs);
1243812491
12439 const ok = if (rhs_ty.zigTypeTag() == .Vector) ok: {
12492 const ok = if (rhs_ty.zigTypeTag(mod) == .Vector) ok: {
1244012493 const eql = try block.addCmpVector(lhs, back, .eq);
1244112494 break :ok try block.addInst(.{
1244212495 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
......@@ -12461,6 +12514,7 @@ fn zirBitwise(
1246112514 const tracy = trace(@src());
1246212515 defer tracy.end();
1246312516
12517 const mod = sema.mod;
1246412518 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1246512519 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1246612520 sema.src = src;
......@@ -12475,8 +12529,8 @@ fn zirBitwise(
1247512529
1247612530 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1247712531 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
12478 const scalar_type = resolved_type.scalarType();
12479 const scalar_tag = scalar_type.zigTypeTag();
12532 const scalar_type = resolved_type.scalarType(mod);
12533 const scalar_tag = scalar_type.zigTypeTag(mod);
1248012534
1248112535 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1248212536 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
......@@ -12484,7 +12538,7 @@ fn zirBitwise(
1248412538 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1248512539
1248612540 if (!is_int) {
12487 return sema.fail(block, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) });
12541 return sema.fail(block, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag(mod)), @tagName(rhs_ty.zigTypeTag(mod)) });
1248812542 }
1248912543
1249012544 const runtime_src = runtime: {
......@@ -12493,9 +12547,9 @@ fn zirBitwise(
1249312547 if (try sema.resolveMaybeUndefValIntable(casted_lhs)) |lhs_val| {
1249412548 if (try sema.resolveMaybeUndefValIntable(casted_rhs)) |rhs_val| {
1249512549 const result_val = switch (air_tag) {
12496 .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena, sema.mod),
12497 .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena, sema.mod),
12498 .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena, sema.mod),
12550 .bit_and => try lhs_val.bitwiseAnd(rhs_val, resolved_type, sema.arena, mod),
12551 .bit_or => try lhs_val.bitwiseOr(rhs_val, resolved_type, sema.arena, mod),
12552 .xor => try lhs_val.bitwiseXor(rhs_val, resolved_type, sema.arena, mod),
1249912553 else => unreachable,
1250012554 };
1250112555 return sema.addConstant(resolved_type, result_val);
......@@ -12515,37 +12569,37 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1251512569 const tracy = trace(@src());
1251612570 defer tracy.end();
1251712571
12572 const mod = sema.mod;
1251812573 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1251912574 const src = inst_data.src();
1252012575 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };
1252112576
1252212577 const operand = try sema.resolveInst(inst_data.operand);
1252312578 const operand_type = sema.typeOf(operand);
12524 const scalar_type = operand_type.scalarType();
12579 const scalar_type = operand_type.scalarType(mod);
1252512580
12526 if (scalar_type.zigTypeTag() != .Int) {
12581 if (scalar_type.zigTypeTag(mod) != .Int) {
1252712582 return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{
12528 operand_type.fmt(sema.mod),
12583 operand_type.fmt(mod),
1252912584 });
1253012585 }
1253112586
1253212587 if (try sema.resolveMaybeUndefVal(operand)) |val| {
12533 if (val.isUndef()) {
12588 if (val.isUndef(mod)) {
1253412589 return sema.addConstUndef(operand_type);
12535 } else if (operand_type.zigTypeTag() == .Vector) {
12536 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen());
12537 var elem_val_buf: Value.ElemValueBuffer = undefined;
12538 const elems = try sema.arena.alloc(Value, vec_len);
12590 } else if (operand_type.zigTypeTag(mod) == .Vector) {
12591 const vec_len = try sema.usizeCast(block, operand_src, operand_type.vectorLen(mod));
12592 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
1253912593 for (elems, 0..) |*elem, i| {
12540 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_val_buf);
12541 elem.* = try elem_val.bitwiseNot(scalar_type, sema.arena, sema.mod);
12594 const elem_val = try val.elemValue(mod, i);
12595 elem.* = try (try elem_val.bitwiseNot(scalar_type, sema.arena, mod)).intern(scalar_type, mod);
1254212596 }
12543 return sema.addConstant(
12544 operand_type,
12545 try Value.Tag.aggregate.create(sema.arena, elems),
12546 );
12597 return sema.addConstant(operand_type, (try mod.intern(.{ .aggregate = .{
12598 .ty = operand_type.toIntern(),
12599 .storage = .{ .elems = elems },
12600 } })).toValue());
1254712601 } else {
12548 const result_val = try val.bitwiseNot(operand_type, sema.arena, sema.mod);
12602 const result_val = try val.bitwiseNot(operand_type, sema.arena, mod);
1254912603 return sema.addConstant(operand_type, result_val);
1255012604 }
1255112605 }
......@@ -12561,18 +12615,19 @@ fn analyzeTupleCat(
1256112615 lhs: Air.Inst.Ref,
1256212616 rhs: Air.Inst.Ref,
1256312617) CompileError!Air.Inst.Ref {
12618 const mod = sema.mod;
1256412619 const lhs_ty = sema.typeOf(lhs);
1256512620 const rhs_ty = sema.typeOf(rhs);
1256612621 const src = LazySrcLoc.nodeOffset(src_node);
1256712622 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
1256812623 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1256912624
12570 const lhs_len = lhs_ty.structFieldCount();
12571 const rhs_len = rhs_ty.structFieldCount();
12625 const lhs_len = lhs_ty.structFieldCount(mod);
12626 const rhs_len = rhs_ty.structFieldCount(mod);
1257212627 const dest_fields = lhs_len + rhs_len;
1257312628
1257412629 if (dest_fields == 0) {
12575 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
12630 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
1257612631 }
1257712632 if (lhs_len == 0) {
1257812633 return rhs;
......@@ -12582,42 +12637,48 @@ fn analyzeTupleCat(
1258212637 }
1258312638 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
1258412639
12585 const types = try sema.arena.alloc(Type, final_len);
12586 const values = try sema.arena.alloc(Value, final_len);
12640 const types = try sema.arena.alloc(InternPool.Index, final_len);
12641 const values = try sema.arena.alloc(InternPool.Index, final_len);
1258712642
1258812643 const opt_runtime_src = rs: {
1258912644 var runtime_src: ?LazySrcLoc = null;
1259012645 var i: u32 = 0;
1259112646 while (i < lhs_len) : (i += 1) {
12592 types[i] = lhs_ty.structFieldType(i);
12593 const default_val = lhs_ty.structFieldDefaultValue(i);
12594 values[i] = default_val;
12647 types[i] = lhs_ty.structFieldType(i, mod).toIntern();
12648 const default_val = lhs_ty.structFieldDefaultValue(i, mod);
12649 values[i] = default_val.toIntern();
1259512650 const operand_src = lhs_src; // TODO better source location
12596 if (default_val.tag() == .unreachable_value) {
12651 if (default_val.toIntern() == .unreachable_value) {
1259712652 runtime_src = operand_src;
12653 values[i] = .none;
1259812654 }
1259912655 }
1260012656 i = 0;
1260112657 while (i < rhs_len) : (i += 1) {
12602 types[i + lhs_len] = rhs_ty.structFieldType(i);
12603 const default_val = rhs_ty.structFieldDefaultValue(i);
12604 values[i + lhs_len] = default_val;
12658 types[i + lhs_len] = rhs_ty.structFieldType(i, mod).toIntern();
12659 const default_val = rhs_ty.structFieldDefaultValue(i, mod);
12660 values[i + lhs_len] = default_val.toIntern();
1260512661 const operand_src = rhs_src; // TODO better source location
12606 if (default_val.tag() == .unreachable_value) {
12662 if (default_val.toIntern() == .unreachable_value) {
1260712663 runtime_src = operand_src;
12664 values[i + lhs_len] = .none;
1260812665 }
1260912666 }
1261012667 break :rs runtime_src;
1261112668 };
1261212669
12613 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
12670 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
1261412671 .types = types,
1261512672 .values = values,
12616 });
12673 .names = &.{},
12674 } });
1261712675
1261812676 const runtime_src = opt_runtime_src orelse {
12619 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
12620 return sema.addConstant(tuple_ty, tuple_val);
12677 const tuple_val = try mod.intern(.{ .aggregate = .{
12678 .ty = tuple_ty,
12679 .storage = .{ .elems = values },
12680 } });
12681 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
1262112682 };
1262212683
1262312684 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -12635,13 +12696,14 @@ fn analyzeTupleCat(
1263512696 try sema.tupleFieldValByIndex(block, operand_src, rhs, i, rhs_ty);
1263612697 }
1263712698
12638 return block.addAggregateInit(tuple_ty, element_refs);
12699 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1263912700}
1264012701
1264112702fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1264212703 const tracy = trace(@src());
1264312704 defer tracy.end();
1264412705
12706 const mod = sema.mod;
1264512707 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1264612708 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1264712709 const lhs = try sema.resolveInst(extra.lhs);
......@@ -12650,8 +12712,8 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1265012712 const rhs_ty = sema.typeOf(rhs);
1265112713 const src = inst_data.src();
1265212714
12653 const lhs_is_tuple = lhs_ty.isTuple();
12654 const rhs_is_tuple = rhs_ty.isTuple();
12715 const lhs_is_tuple = lhs_ty.isTuple(mod);
12716 const rhs_is_tuple = rhs_ty.isTuple(mod);
1265512717 if (lhs_is_tuple and rhs_is_tuple) {
1265612718 return sema.analyzeTupleCat(block, inst_data.src_node, lhs, rhs);
1265712719 }
......@@ -12661,11 +12723,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1266112723
1266212724 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, rhs_ty) orelse lhs_info: {
1266312725 if (lhs_is_tuple) break :lhs_info @as(Type.ArrayInfo, undefined);
12664 return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)});
12726 return sema.fail(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(mod)});
1266512727 };
1266612728 const rhs_info = try sema.getArrayCatInfo(block, rhs_src, rhs, lhs_ty) orelse {
1266712729 assert(!rhs_is_tuple);
12668 return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(sema.mod)});
12730 return sema.fail(block, rhs_src, "expected indexable; found '{}'", .{rhs_ty.fmt(mod)});
1266912731 };
1267012732
1267112733 const resolved_elem_ty = t: {
......@@ -12727,73 +12789,71 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1272712789 ),
1272812790 };
1272912791
12730 const result_ty = try Type.array(sema.arena, result_len, res_sent_val, resolved_elem_ty, sema.mod);
12792 const result_ty = try Type.array(sema.arena, result_len, res_sent_val, resolved_elem_ty, mod);
1273112793 const ptr_addrspace = p: {
12732 if (lhs_ty.zigTypeTag() == .Pointer) break :p lhs_ty.ptrAddressSpace();
12733 if (rhs_ty.zigTypeTag() == .Pointer) break :p rhs_ty.ptrAddressSpace();
12794 if (lhs_ty.zigTypeTag(mod) == .Pointer) break :p lhs_ty.ptrAddressSpace(mod);
12795 if (rhs_ty.zigTypeTag(mod) == .Pointer) break :p rhs_ty.ptrAddressSpace(mod);
1273412796 break :p null;
1273512797 };
1273612798
12737 const runtime_src = if (switch (lhs_ty.zigTypeTag()) {
12799 const runtime_src = if (switch (lhs_ty.zigTypeTag(mod)) {
1273812800 .Array, .Struct => try sema.resolveMaybeUndefVal(lhs),
1273912801 .Pointer => try sema.resolveDefinedValue(block, lhs_src, lhs),
1274012802 else => unreachable,
1274112803 }) |lhs_val| rs: {
12742 if (switch (rhs_ty.zigTypeTag()) {
12804 if (switch (rhs_ty.zigTypeTag(mod)) {
1274312805 .Array, .Struct => try sema.resolveMaybeUndefVal(rhs),
1274412806 .Pointer => try sema.resolveDefinedValue(block, rhs_src, rhs),
1274512807 else => unreachable,
1274612808 }) |rhs_val| {
12747 const lhs_sub_val = if (lhs_ty.isSinglePointer())
12809 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
1274812810 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
1274912811 else
1275012812 lhs_val;
1275112813
12752 const rhs_sub_val = if (rhs_ty.isSinglePointer())
12814 const rhs_sub_val = if (rhs_ty.isSinglePointer(mod))
1275312815 (try sema.pointerDeref(block, rhs_src, rhs_val, rhs_ty)).?
1275412816 else
1275512817 rhs_val;
1275612818
12757 const final_len_including_sent = result_len + @boolToInt(res_sent_val != null);
12758 const element_vals = try sema.arena.alloc(Value, final_len_including_sent);
12819 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
1275912820 var elem_i: usize = 0;
1276012821 while (elem_i < lhs_len) : (elem_i += 1) {
1276112822 const lhs_elem_i = elem_i;
12762 const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i) else lhs_info.elem_type;
12763 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i) else Value.initTag(.unreachable_value);
12764 const elem_val = if (elem_default_val.tag() == .unreachable_value) try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_elem_i) else elem_default_val;
12823 const elem_ty = if (lhs_is_tuple) lhs_ty.structFieldType(lhs_elem_i, mod) else lhs_info.elem_type;
12824 const elem_default_val = if (lhs_is_tuple) lhs_ty.structFieldDefaultValue(lhs_elem_i, mod) else Value.@"unreachable";
12825 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try lhs_sub_val.elemValue(mod, lhs_elem_i) else elem_default_val;
1276512826 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
1276612827 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
1276712828 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");
12768 element_vals[elem_i] = coerced_elem_val;
12829 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
1276912830 }
1277012831 while (elem_i < result_len) : (elem_i += 1) {
1277112832 const rhs_elem_i = elem_i - lhs_len;
12772 const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i) else rhs_info.elem_type;
12773 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i) else Value.initTag(.unreachable_value);
12774 const elem_val = if (elem_default_val.tag() == .unreachable_value) try rhs_sub_val.elemValue(sema.mod, sema.arena, rhs_elem_i) else elem_default_val;
12833 const elem_ty = if (rhs_is_tuple) rhs_ty.structFieldType(rhs_elem_i, mod) else rhs_info.elem_type;
12834 const elem_default_val = if (rhs_is_tuple) rhs_ty.structFieldDefaultValue(rhs_elem_i, mod) else Value.@"unreachable";
12835 const elem_val = if (elem_default_val.toIntern() == .unreachable_value) try rhs_sub_val.elemValue(mod, rhs_elem_i) else elem_default_val;
1277512836 const elem_val_inst = try sema.addConstant(elem_ty, elem_val);
1277612837 const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, .unneeded);
1277712838 const coerced_elem_val = try sema.resolveConstMaybeUndefVal(block, .unneeded, coerced_elem_val_inst, "");
12778 element_vals[elem_i] = coerced_elem_val;
12839 element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod);
1277912840 }
12780 if (res_sent_val) |sent_val| {
12781 element_vals[result_len] = sent_val;
12782 }
12783 const val = try Value.Tag.aggregate.create(sema.arena, element_vals);
12784 return sema.addConstantMaybeRef(block, result_ty, val, ptr_addrspace != null);
12841 return sema.addConstantMaybeRef(block, result_ty, (try mod.intern(.{ .aggregate = .{
12842 .ty = result_ty.toIntern(),
12843 .storage = .{ .elems = element_vals },
12844 } })).toValue(), ptr_addrspace != null);
1278512845 } else break :rs rhs_src;
1278612846 } else lhs_src;
1278712847
1278812848 try sema.requireRuntimeBlock(block, src, runtime_src);
1278912849
1279012850 if (ptr_addrspace) |ptr_as| {
12791 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
12851 const alloc_ty = try Type.ptr(sema.arena, mod, .{
1279212852 .pointee_type = result_ty,
1279312853 .@"addrspace" = ptr_as,
1279412854 });
1279512855 const alloc = try block.addTy(.alloc, alloc_ty);
12796 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
12856 const elem_ptr_ty = try Type.ptr(sema.arena, mod, .{
1279712857 .pointee_type = resolved_elem_ty,
1279812858 .@"addrspace" = ptr_as,
1279912859 });
......@@ -12815,7 +12875,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1281512875 if (res_sent_val) |sent_val| {
1281612876 const elem_index = try sema.addIntUnsigned(Type.usize, result_len);
1281712877 const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);
12818 const init = try sema.addConstant(lhs_info.elem_type, sent_val);
12878 const init = try sema.addConstant(lhs_info.elem_type, try mod.getCoerced(sent_val, lhs_info.elem_type));
1281912879 try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
1282012880 }
1282112881
......@@ -12841,11 +12901,12 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1284112901}
1284212902
1284312903fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, peer_ty: Type) !?Type.ArrayInfo {
12904 const mod = sema.mod;
1284412905 const operand_ty = sema.typeOf(operand);
12845 switch (operand_ty.zigTypeTag()) {
12846 .Array => return operand_ty.arrayInfo(),
12906 switch (operand_ty.zigTypeTag(mod)) {
12907 .Array => return operand_ty.arrayInfo(mod),
1284712908 .Pointer => {
12848 const ptr_info = operand_ty.ptrInfo().data;
12909 const ptr_info = operand_ty.ptrInfo(mod);
1284912910 switch (ptr_info.size) {
1285012911 // TODO: in the Many case here this should only work if the type
1285112912 // has a sentinel, and this code should compute the length based
......@@ -12855,24 +12916,24 @@ fn getArrayCatInfo(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Ins
1285512916 return Type.ArrayInfo{
1285612917 .elem_type = ptr_info.pointee_type,
1285712918 .sentinel = ptr_info.sentinel,
12858 .len = val.sliceLen(sema.mod),
12919 .len = val.sliceLen(mod),
1285912920 };
1286012921 },
1286112922 .One => {
12862 if (ptr_info.pointee_type.zigTypeTag() == .Array) {
12863 return ptr_info.pointee_type.arrayInfo();
12923 if (ptr_info.pointee_type.zigTypeTag(mod) == .Array) {
12924 return ptr_info.pointee_type.arrayInfo(mod);
1286412925 }
1286512926 },
1286612927 .C => {},
1286712928 }
1286812929 },
1286912930 .Struct => {
12870 if (operand_ty.isTuple() and peer_ty.isIndexable()) {
12871 assert(!peer_ty.isTuple());
12931 if (operand_ty.isTuple(mod) and peer_ty.isIndexable(mod)) {
12932 assert(!peer_ty.isTuple(mod));
1287212933 return .{
12873 .elem_type = peer_ty.elemType2(),
12934 .elem_type = peer_ty.elemType2(mod),
1287412935 .sentinel = null,
12875 .len = operand_ty.arrayLen(),
12936 .len = operand_ty.arrayLen(mod),
1287612937 };
1287712938 }
1287812939 },
......@@ -12886,52 +12947,54 @@ fn analyzeTupleMul(
1288612947 block: *Block,
1288712948 src_node: i32,
1288812949 operand: Air.Inst.Ref,
12889 factor: u64,
12950 factor: usize,
1289012951) CompileError!Air.Inst.Ref {
12952 const mod = sema.mod;
1289112953 const operand_ty = sema.typeOf(operand);
1289212954 const src = LazySrcLoc.nodeOffset(src_node);
1289312955 const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = src_node };
1289412956 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = src_node };
1289512957
12896 const tuple_len = operand_ty.structFieldCount();
12897 const final_len_u64 = std.math.mul(u64, tuple_len, factor) catch
12958 const tuple_len = operand_ty.structFieldCount(mod);
12959 const final_len = std.math.mul(usize, tuple_len, factor) catch
1289812960 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1289912961
12900 if (final_len_u64 == 0) {
12901 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
12962 if (final_len == 0) {
12963 return sema.addConstant(Type.empty_struct_literal, Value.empty_struct);
1290212964 }
12903 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);
12904
12905 const types = try sema.arena.alloc(Type, final_len);
12906 const values = try sema.arena.alloc(Value, final_len);
12965 const types = try sema.arena.alloc(InternPool.Index, final_len);
12966 const values = try sema.arena.alloc(InternPool.Index, final_len);
1290712967
1290812968 const opt_runtime_src = rs: {
1290912969 var runtime_src: ?LazySrcLoc = null;
12910 var i: u32 = 0;
12911 while (i < tuple_len) : (i += 1) {
12912 types[i] = operand_ty.structFieldType(i);
12913 values[i] = operand_ty.structFieldDefaultValue(i);
12970 for (0..tuple_len) |i| {
12971 types[i] = operand_ty.structFieldType(i, mod).toIntern();
12972 values[i] = operand_ty.structFieldDefaultValue(i, mod).toIntern();
1291412973 const operand_src = lhs_src; // TODO better source location
12915 if (values[i].tag() == .unreachable_value) {
12974 if (values[i] == .unreachable_value) {
1291612975 runtime_src = operand_src;
12976 values[i] = .none; // TODO don't treat unreachable_value as special
1291712977 }
1291812978 }
12919 i = 0;
12920 while (i < factor) : (i += 1) {
12921 mem.copyForwards(Type, types[tuple_len * i ..], types[0..tuple_len]);
12922 mem.copyForwards(Value, values[tuple_len * i ..], values[0..tuple_len]);
12979 for (0..factor) |i| {
12980 mem.copyForwards(InternPool.Index, types[tuple_len * i ..], types[0..tuple_len]);
12981 mem.copyForwards(InternPool.Index, values[tuple_len * i ..], values[0..tuple_len]);
1292312982 }
1292412983 break :rs runtime_src;
1292512984 };
1292612985
12927 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
12986 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
1292812987 .types = types,
1292912988 .values = values,
12930 });
12989 .names = &.{},
12990 } });
1293112991
1293212992 const runtime_src = opt_runtime_src orelse {
12933 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
12934 return sema.addConstant(tuple_ty, tuple_val);
12993 const tuple_val = try mod.intern(.{ .aggregate = .{
12994 .ty = tuple_ty,
12995 .storage = .{ .elems = values },
12996 } });
12997 return sema.addConstant(tuple_ty.toType(), tuple_val.toValue());
1293512998 };
1293612999
1293713000 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -12947,13 +13010,14 @@ fn analyzeTupleMul(
1294713010 @memcpy(element_refs[tuple_len * i ..][0..tuple_len], element_refs[0..tuple_len]);
1294813011 }
1294913012
12950 return block.addAggregateInit(tuple_ty, element_refs);
13013 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1295113014}
1295213015
1295313016fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1295413017 const tracy = trace(@src());
1295513018 defer tracy.end();
1295613019
13020 const mod = sema.mod;
1295713021 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1295813022 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1295913023 const lhs = try sema.resolveInst(extra.lhs);
......@@ -12963,18 +13027,19 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1296313027 const operator_src: LazySrcLoc = .{ .node_offset_main_token = inst_data.src_node };
1296413028 const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
1296513029
12966 if (lhs_ty.isTuple()) {
13030 if (lhs_ty.isTuple(mod)) {
1296713031 // In `**` rhs must be comptime-known, but lhs can be runtime-known
1296813032 const factor = try sema.resolveInt(block, rhs_src, extra.rhs, Type.usize, "array multiplication factor must be comptime-known");
12969 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor);
13033 const factor_casted = try sema.usizeCast(block, rhs_src, factor);
13034 return sema.analyzeTupleMul(block, inst_data.src_node, lhs, factor_casted);
1297013035 }
1297113036
1297213037 // Analyze the lhs first, to catch the case that someone tried to do exponentiation
1297313038 const lhs_info = try sema.getArrayCatInfo(block, lhs_src, lhs, lhs_ty) orelse {
1297413039 const msg = msg: {
12975 const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(sema.mod)});
13040 const msg = try sema.errMsg(block, lhs_src, "expected indexable; found '{}'", .{lhs_ty.fmt(mod)});
1297613041 errdefer msg.destroy(sema.gpa);
12977 switch (lhs_ty.zigTypeTag()) {
13042 switch (lhs_ty.zigTypeTag(mod)) {
1297813043 .Int, .Float, .ComptimeFloat, .ComptimeInt, .Vector => {
1297913044 try sema.errNote(block, operator_src, msg, "this operator multiplies arrays; use std.math.pow for exponentiation", .{});
1298013045 },
......@@ -12992,15 +13057,13 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1299213057 return sema.fail(block, rhs_src, "operation results in overflow", .{});
1299313058 const result_len = try sema.usizeCast(block, src, result_len_u64);
1299413059
12995 const result_ty = try Type.array(sema.arena, result_len, lhs_info.sentinel, lhs_info.elem_type, sema.mod);
13060 const result_ty = try Type.array(sema.arena, result_len, lhs_info.sentinel, lhs_info.elem_type, mod);
1299613061
12997 const ptr_addrspace = if (lhs_ty.zigTypeTag() == .Pointer) lhs_ty.ptrAddressSpace() else null;
13062 const ptr_addrspace = if (lhs_ty.zigTypeTag(mod) == .Pointer) lhs_ty.ptrAddressSpace(mod) else null;
1299813063 const lhs_len = try sema.usizeCast(block, lhs_src, lhs_info.len);
1299913064
1300013065 if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
13001 const final_len_including_sent = result_len + @boolToInt(lhs_info.sentinel != null);
13002
13003 const lhs_sub_val = if (lhs_ty.isSinglePointer())
13066 const lhs_sub_val = if (lhs_ty.isSinglePointer(mod))
1300413067 (try sema.pointerDeref(block, lhs_src, lhs_val, lhs_ty)).?
1300513068 else
1300613069 lhs_val;
......@@ -13008,38 +13071,41 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1300813071 const val = v: {
1300913072 // Optimization for the common pattern of a single element repeated N times, such
1301013073 // as zero-filling a byte array.
13011 if (lhs_len == 1) {
13012 const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, 0);
13013 break :v try Value.Tag.repeated.create(sema.arena, elem_val);
13074 if (lhs_len == 1 and lhs_info.sentinel == null) {
13075 const elem_val = try lhs_sub_val.elemValue(mod, 0);
13076 break :v try mod.intern(.{ .aggregate = .{
13077 .ty = result_ty.toIntern(),
13078 .storage = .{ .repeated_elem = elem_val.toIntern() },
13079 } });
1301413080 }
1301513081
13016 const element_vals = try sema.arena.alloc(Value, final_len_including_sent);
13082 const element_vals = try sema.arena.alloc(InternPool.Index, result_len);
1301713083 var elem_i: usize = 0;
1301813084 while (elem_i < result_len) {
1301913085 var lhs_i: usize = 0;
1302013086 while (lhs_i < lhs_len) : (lhs_i += 1) {
13021 const elem_val = try lhs_sub_val.elemValue(sema.mod, sema.arena, lhs_i);
13022 element_vals[elem_i] = elem_val;
13087 const elem_val = try lhs_sub_val.elemValue(mod, lhs_i);
13088 element_vals[elem_i] = elem_val.toIntern();
1302313089 elem_i += 1;
1302413090 }
1302513091 }
13026 if (lhs_info.sentinel) |sent_val| {
13027 element_vals[result_len] = sent_val;
13028 }
13029 break :v try Value.Tag.aggregate.create(sema.arena, element_vals);
13092 break :v try mod.intern(.{ .aggregate = .{
13093 .ty = result_ty.toIntern(),
13094 .storage = .{ .elems = element_vals },
13095 } });
1303013096 };
13031 return sema.addConstantMaybeRef(block, result_ty, val, ptr_addrspace != null);
13097 return sema.addConstantMaybeRef(block, result_ty, val.toValue(), ptr_addrspace != null);
1303213098 }
1303313099
1303413100 try sema.requireRuntimeBlock(block, src, lhs_src);
1303513101
1303613102 if (ptr_addrspace) |ptr_as| {
13037 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
13103 const alloc_ty = try Type.ptr(sema.arena, mod, .{
1303813104 .pointee_type = result_ty,
1303913105 .@"addrspace" = ptr_as,
1304013106 });
1304113107 const alloc = try block.addTy(.alloc, alloc_ty);
13042 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
13108 const elem_ptr_ty = try Type.ptr(sema.arena, mod, .{
1304313109 .pointee_type = lhs_info.elem_type,
1304413110 .@"addrspace" = ptr_as,
1304513111 });
......@@ -13082,6 +13148,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1308213148}
1308313149
1308413150fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13151 const mod = sema.mod;
1308513152 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1308613153 const src = inst_data.src();
1308713154 const lhs_src = src;
......@@ -13089,34 +13156,31 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1308913156
1309013157 const rhs = try sema.resolveInst(inst_data.operand);
1309113158 const rhs_ty = sema.typeOf(rhs);
13092 const rhs_scalar_ty = rhs_ty.scalarType();
13159 const rhs_scalar_ty = rhs_ty.scalarType(mod);
1309313160
13094 if (rhs_scalar_ty.isUnsignedInt() or switch (rhs_scalar_ty.zigTypeTag()) {
13161 if (rhs_scalar_ty.isUnsignedInt(mod) or switch (rhs_scalar_ty.zigTypeTag(mod)) {
1309513162 .Int, .ComptimeInt, .Float, .ComptimeFloat => false,
1309613163 else => true,
1309713164 }) {
13098 return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)});
13165 return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(mod)});
1309913166 }
1310013167
1310113168 if (rhs_scalar_ty.isAnyFloat()) {
1310213169 // We handle float negation here to ensure negative zero is represented in the bits.
1310313170 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
13104 if (rhs_val.isUndef()) return sema.addConstUndef(rhs_ty);
13105 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, sema.mod));
13171 if (rhs_val.isUndef(mod)) return sema.addConstUndef(rhs_ty);
13172 return sema.addConstant(rhs_ty, try rhs_val.floatNeg(rhs_ty, sema.arena, mod));
1310613173 }
1310713174 try sema.requireRuntimeBlock(block, src, null);
1310813175 return block.addUnOp(if (block.float_mode == .Optimized) .neg_optimized else .neg, rhs);
1310913176 }
1311013177
13111 const lhs = if (rhs_ty.zigTypeTag() == .Vector)
13112 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
13113 else
13114 try sema.resolveInst(.zero);
13115
13178 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
1311613179 return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
1311713180}
1311813181
1311913182fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13183 const mod = sema.mod;
1312013184 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1312113185 const src = inst_data.src();
1312213186 const lhs_src = src;
......@@ -13124,18 +13188,14 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1312413188
1312513189 const rhs = try sema.resolveInst(inst_data.operand);
1312613190 const rhs_ty = sema.typeOf(rhs);
13127 const rhs_scalar_ty = rhs_ty.scalarType();
13191 const rhs_scalar_ty = rhs_ty.scalarType(mod);
1312813192
13129 switch (rhs_scalar_ty.zigTypeTag()) {
13193 switch (rhs_scalar_ty.zigTypeTag(mod)) {
1313013194 .Int, .ComptimeInt, .Float, .ComptimeFloat => {},
13131 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(sema.mod)}),
13195 else => return sema.fail(block, src, "negation of type '{}'", .{rhs_ty.fmt(mod)}),
1313213196 }
1313313197
13134 const lhs = if (rhs_ty.zigTypeTag() == .Vector)
13135 try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
13136 else
13137 try sema.resolveInst(.zero);
13138
13198 const lhs = try sema.addConstant(rhs_ty, try sema.splat(rhs_ty, try mod.intValue(rhs_scalar_ty, 0)));
1313913199 return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
1314013200}
1314113201
......@@ -13161,6 +13221,7 @@ fn zirArithmetic(
1316113221}
1316213222
1316313223fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13224 const mod = sema.mod;
1316413225 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1316513226 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1316613227 sema.src = src;
......@@ -13171,8 +13232,8 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1317113232 const rhs = try sema.resolveInst(extra.rhs);
1317213233 const lhs_ty = sema.typeOf(lhs);
1317313234 const rhs_ty = sema.typeOf(rhs);
13174 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13175 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13235 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13236 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1317613237 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1317713238 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1317813239
......@@ -13181,25 +13242,22 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1318113242 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1318213243 });
1318313244
13184 const is_vector = resolved_type.zigTypeTag() == .Vector;
13185
1318613245 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1318713246 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1318813247
13189 const lhs_scalar_ty = lhs_ty.scalarType();
13190 const rhs_scalar_ty = rhs_ty.scalarType();
13191 const scalar_tag = resolved_type.scalarType().zigTypeTag();
13248 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13249 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13250 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1319213251
1319313252 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1319413253
1319513254 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div);
1319613255
13197 const mod = sema.mod;
1319813256 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1319913257 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1320013258
13201 if ((lhs_ty.zigTypeTag() == .ComptimeFloat and rhs_ty.zigTypeTag() == .ComptimeInt) or
13202 (lhs_ty.zigTypeTag() == .ComptimeInt and rhs_ty.zigTypeTag() == .ComptimeFloat))
13259 if ((lhs_ty.zigTypeTag(mod) == .ComptimeFloat and rhs_ty.zigTypeTag(mod) == .ComptimeInt) or
13260 (lhs_ty.zigTypeTag(mod) == .ComptimeInt and rhs_ty.zigTypeTag(mod) == .ComptimeFloat))
1320313261 {
1320413262 // If it makes a difference whether we coerce to ints or floats before doing the division, error.
1320513263 // If lhs % rhs is 0, it doesn't matter.
......@@ -13207,9 +13265,12 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1320713265 const rhs_val = maybe_rhs_val orelse unreachable;
1320813266 const rem = lhs_val.floatRem(rhs_val, resolved_type, sema.arena, mod) catch unreachable;
1320913267 if (!rem.compareAllWithZero(.eq, mod)) {
13210 return sema.fail(block, src, "ambiguous coercion of division operands '{s}' and '{s}'; non-zero remainder '{}'", .{
13211 @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()), rem.fmtValue(resolved_type, sema.mod),
13212 });
13268 return sema.fail(
13269 block,
13270 src,
13271 "ambiguous coercion of division operands '{}' and '{}'; non-zero remainder '{}'",
13272 .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod), rem.fmtValue(resolved_type, mod) },
13273 );
1321313274 }
1321413275 }
1321513276
......@@ -13243,17 +13304,20 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1324313304 switch (scalar_tag) {
1324413305 .Int, .ComptimeInt, .ComptimeFloat => {
1324513306 if (maybe_lhs_val) |lhs_val| {
13246 if (!lhs_val.isUndef()) {
13307 if (!lhs_val.isUndef(mod)) {
1324713308 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13248 const zero_val = if (is_vector) b: {
13249 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13250 } else Value.zero;
13309 const scalar_zero = switch (scalar_tag) {
13310 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13311 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13312 else => unreachable,
13313 };
13314 const zero_val = try sema.splat(resolved_type, scalar_zero);
1325113315 return sema.addConstant(resolved_type, zero_val);
1325213316 }
1325313317 }
1325413318 }
1325513319 if (maybe_rhs_val) |rhs_val| {
13256 if (rhs_val.isUndef()) {
13320 if (rhs_val.isUndef(mod)) {
1325713321 return sema.failWithUseOfUndef(block, rhs_src);
1325813322 }
1325913323 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -13267,10 +13331,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1326713331
1326813332 const runtime_src = rs: {
1326913333 if (maybe_lhs_val) |lhs_val| {
13270 if (lhs_val.isUndef()) {
13271 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
13334 if (lhs_val.isUndef(mod)) {
13335 if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
1327213336 if (maybe_rhs_val) |rhs_val| {
13273 if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) {
13337 if (try sema.compareAll(rhs_val, .neq, try mod.intValue(resolved_type, -1), resolved_type)) {
1327413338 return sema.addConstUndef(resolved_type);
1327513339 }
1327613340 }
......@@ -13281,10 +13345,10 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1328113345
1328213346 if (maybe_rhs_val) |rhs_val| {
1328313347 if (is_int) {
13284 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);
13285 var vector_index: usize = undefined;
13286 if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) {
13287 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index);
13348 var overflow_idx: ?usize = null;
13349 const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
13350 if (overflow_idx) |vec_idx| {
13351 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx);
1328813352 }
1328913353 return sema.addConstant(resolved_type, res);
1329013354 } else {
......@@ -13309,8 +13373,13 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1330913373 }
1331013374
1331113375 const air_tag = if (is_int) blk: {
13312 if (lhs_ty.isSignedInt() or rhs_ty.isSignedInt()) {
13313 return sema.fail(block, src, "division with '{s}' and '{s}': signed integers must use @divTrunc, @divFloor, or @divExact", .{ @tagName(lhs_ty.tag()), @tagName(rhs_ty.tag()) });
13376 if (lhs_ty.isSignedInt(mod) or rhs_ty.isSignedInt(mod)) {
13377 return sema.fail(
13378 block,
13379 src,
13380 "division with '{}' and '{}': signed integers must use @divTrunc, @divFloor, or @divExact",
13381 .{ lhs_ty.fmt(mod), rhs_ty.fmt(mod) },
13382 );
1331413383 }
1331513384 break :blk Air.Inst.Tag.div_trunc;
1331613385 } else switch (block.float_mode) {
......@@ -13321,6 +13390,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1332113390}
1332213391
1332313392fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13393 const mod = sema.mod;
1332413394 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1332513395 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1332613396 sema.src = src;
......@@ -13331,8 +13401,8 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1333113401 const rhs = try sema.resolveInst(extra.rhs);
1333213402 const lhs_ty = sema.typeOf(lhs);
1333313403 const rhs_ty = sema.typeOf(rhs);
13334 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13335 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13404 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13405 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1333613406 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1333713407 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1333813408
......@@ -13341,19 +13411,16 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1334113411 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1334213412 });
1334313413
13344 const is_vector = resolved_type.zigTypeTag() == .Vector;
13345
1334613414 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1334713415 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1334813416
13349 const lhs_scalar_ty = lhs_ty.scalarType();
13350 const scalar_tag = resolved_type.scalarType().zigTypeTag();
13417 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13418 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1335113419
1335213420 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1335313421
1335413422 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_exact);
1335513423
13356 const mod = sema.mod;
1335713424 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1335813425 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1335913426
......@@ -13375,19 +13442,22 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1337513442 // If the lhs is undefined, compile error because there is a possible
1337613443 // value for which the division would result in a remainder.
1337713444 if (maybe_lhs_val) |lhs_val| {
13378 if (lhs_val.isUndef()) {
13445 if (lhs_val.isUndef(mod)) {
1337913446 return sema.failWithUseOfUndef(block, rhs_src);
1338013447 } else {
1338113448 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13382 const zero_val = if (is_vector) b: {
13383 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13384 } else Value.zero;
13449 const scalar_zero = switch (scalar_tag) {
13450 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13451 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13452 else => unreachable,
13453 };
13454 const zero_val = try sema.splat(resolved_type, scalar_zero);
1338513455 return sema.addConstant(resolved_type, zero_val);
1338613456 }
1338713457 }
1338813458 }
1338913459 if (maybe_rhs_val) |rhs_val| {
13390 if (rhs_val.isUndef()) {
13460 if (rhs_val.isUndef(mod)) {
1339113461 return sema.failWithUseOfUndef(block, rhs_src);
1339213462 }
1339313463 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -13402,10 +13472,10 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1340213472 if (!(modulus_val.compareAllWithZero(.eq, mod))) {
1340313473 return sema.fail(block, src, "exact division produced remainder", .{});
1340413474 }
13405 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);
13406 var vector_index: usize = undefined;
13407 if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) {
13408 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index);
13475 var overflow_idx: ?usize = null;
13476 const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
13477 if (overflow_idx) |vec_idx| {
13478 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx);
1340913479 }
1341013480 return sema.addConstant(resolved_type, res);
1341113481 } else {
......@@ -13437,7 +13507,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1343713507 const ok = if (!is_int) ok: {
1343813508 const floored = try block.addUnOp(.floor, result);
1343913509
13440 if (resolved_type.zigTypeTag() == .Vector) {
13510 if (resolved_type.zigTypeTag(mod) == .Vector) {
1344113511 const eql = try block.addCmpVector(result, floored, .eq);
1344213512 break :ok try block.addInst(.{
1344313513 .tag = switch (block.float_mode) {
......@@ -13459,8 +13529,13 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1345913529 } else ok: {
1346013530 const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
1346113531
13462 if (resolved_type.zigTypeTag() == .Vector) {
13463 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
13532 const scalar_zero = switch (scalar_tag) {
13533 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13534 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13535 else => unreachable,
13536 };
13537 if (resolved_type.zigTypeTag(mod) == .Vector) {
13538 const zero_val = try sema.splat(resolved_type, scalar_zero);
1346413539 const zero = try sema.addConstant(resolved_type, zero_val);
1346513540 const eql = try block.addCmpVector(remainder, zero, .eq);
1346613541 break :ok try block.addInst(.{
......@@ -13471,7 +13546,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1347113546 } },
1347213547 });
1347313548 } else {
13474 const zero = try sema.addConstant(resolved_type, Value.zero);
13549 const zero = try sema.addConstant(resolved_type, scalar_zero);
1347513550 const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
1347613551 break :ok is_in_range;
1347713552 }
......@@ -13484,6 +13559,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1348413559}
1348513560
1348613561fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13562 const mod = sema.mod;
1348713563 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1348813564 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1348913565 sema.src = src;
......@@ -13494,8 +13570,8 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1349413570 const rhs = try sema.resolveInst(extra.rhs);
1349513571 const lhs_ty = sema.typeOf(lhs);
1349613572 const rhs_ty = sema.typeOf(rhs);
13497 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13498 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13573 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13574 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1349913575 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1350013576 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1350113577
......@@ -13504,20 +13580,17 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1350413580 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1350513581 });
1350613582
13507 const is_vector = resolved_type.zigTypeTag() == .Vector;
13508
1350913583 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1351013584 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1351113585
13512 const lhs_scalar_ty = lhs_ty.scalarType();
13513 const rhs_scalar_ty = rhs_ty.scalarType();
13514 const scalar_tag = resolved_type.scalarType().zigTypeTag();
13586 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13587 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13588 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1351513589
1351613590 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1351713591
1351813592 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_floor);
1351913593
13520 const mod = sema.mod;
1352113594 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1352213595 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1352313596
......@@ -13542,17 +13615,20 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1354213615 // value (zero) for which the division would be illegal behavior.
1354313616 // If the lhs is undefined, result is undefined.
1354413617 if (maybe_lhs_val) |lhs_val| {
13545 if (!lhs_val.isUndef()) {
13618 if (!lhs_val.isUndef(mod)) {
1354613619 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13547 const zero_val = if (is_vector) b: {
13548 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13549 } else Value.zero;
13620 const scalar_zero = switch (scalar_tag) {
13621 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13622 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13623 else => unreachable,
13624 };
13625 const zero_val = try sema.splat(resolved_type, scalar_zero);
1355013626 return sema.addConstant(resolved_type, zero_val);
1355113627 }
1355213628 }
1355313629 }
1355413630 if (maybe_rhs_val) |rhs_val| {
13555 if (rhs_val.isUndef()) {
13631 if (rhs_val.isUndef(mod)) {
1355613632 return sema.failWithUseOfUndef(block, rhs_src);
1355713633 }
1355813634 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -13561,10 +13637,10 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1356113637 // TODO: if the RHS is one, return the LHS directly
1356213638 }
1356313639 if (maybe_lhs_val) |lhs_val| {
13564 if (lhs_val.isUndef()) {
13565 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
13640 if (lhs_val.isUndef(mod)) {
13641 if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
1356613642 if (maybe_rhs_val) |rhs_val| {
13567 if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) {
13643 if (try sema.compareAll(rhs_val, .neq, try mod.intValue(resolved_type, -1), resolved_type)) {
1356813644 return sema.addConstUndef(resolved_type);
1356913645 }
1357013646 }
......@@ -13600,6 +13676,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1360013676}
1360113677
1360213678fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13679 const mod = sema.mod;
1360313680 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1360413681 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1360513682 sema.src = src;
......@@ -13610,8 +13687,8 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1361013687 const rhs = try sema.resolveInst(extra.rhs);
1361113688 const lhs_ty = sema.typeOf(lhs);
1361213689 const rhs_ty = sema.typeOf(rhs);
13613 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13614 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13690 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13691 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1361513692 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1361613693 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1361713694
......@@ -13620,20 +13697,17 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1362013697 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1362113698 });
1362213699
13623 const is_vector = resolved_type.zigTypeTag() == .Vector;
13624
1362513700 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1362613701 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1362713702
13628 const lhs_scalar_ty = lhs_ty.scalarType();
13629 const rhs_scalar_ty = rhs_ty.scalarType();
13630 const scalar_tag = resolved_type.scalarType().zigTypeTag();
13703 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13704 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13705 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1363113706
1363213707 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1363313708
1363413709 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .div_trunc);
1363513710
13636 const mod = sema.mod;
1363713711 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1363813712 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1363913713
......@@ -13658,17 +13732,20 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1365813732 // value (zero) for which the division would be illegal behavior.
1365913733 // If the lhs is undefined, result is undefined.
1366013734 if (maybe_lhs_val) |lhs_val| {
13661 if (!lhs_val.isUndef()) {
13735 if (!lhs_val.isUndef(mod)) {
1366213736 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13663 const zero_val = if (is_vector) b: {
13664 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13665 } else Value.zero;
13737 const scalar_zero = switch (scalar_tag) {
13738 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13739 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13740 else => unreachable,
13741 };
13742 const zero_val = try sema.splat(resolved_type, scalar_zero);
1366613743 return sema.addConstant(resolved_type, zero_val);
1366713744 }
1366813745 }
1366913746 }
1367013747 if (maybe_rhs_val) |rhs_val| {
13671 if (rhs_val.isUndef()) {
13748 if (rhs_val.isUndef(mod)) {
1367213749 return sema.failWithUseOfUndef(block, rhs_src);
1367313750 }
1367413751 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -13676,10 +13753,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1367613753 }
1367713754 }
1367813755 if (maybe_lhs_val) |lhs_val| {
13679 if (lhs_val.isUndef()) {
13680 if (lhs_scalar_ty.isSignedInt() and rhs_scalar_ty.isSignedInt()) {
13756 if (lhs_val.isUndef(mod)) {
13757 if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
1368113758 if (maybe_rhs_val) |rhs_val| {
13682 if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) {
13759 if (try sema.compareAll(rhs_val, .neq, try mod.intValue(resolved_type, -1), resolved_type)) {
1368313760 return sema.addConstUndef(resolved_type);
1368413761 }
1368513762 }
......@@ -13690,10 +13767,10 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1369013767
1369113768 if (maybe_rhs_val) |rhs_val| {
1369213769 if (is_int) {
13693 const res = try lhs_val.intDiv(rhs_val, resolved_type, sema.arena, mod);
13694 var vector_index: usize = undefined;
13695 if (!(try sema.intFitsInType(res, resolved_type, &vector_index))) {
13696 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vector_index);
13770 var overflow_idx: ?usize = null;
13771 const res = try lhs_val.intDiv(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
13772 if (overflow_idx) |vec_idx| {
13773 return sema.failWithIntegerOverflow(block, src, resolved_type, res, vec_idx);
1369713774 }
1369813775 return sema.addConstant(resolved_type, res);
1369913776 } else {
......@@ -13727,39 +13804,34 @@ fn addDivIntOverflowSafety(
1372713804 casted_rhs: Air.Inst.Ref,
1372813805 is_int: bool,
1372913806) CompileError!void {
13807 const mod = sema.mod;
1373013808 if (!is_int) return;
1373113809
1373213810 // If the LHS is unsigned, it cannot cause overflow.
13733 if (!lhs_scalar_ty.isSignedInt()) return;
13734
13735 const mod = sema.mod;
13736 const target = mod.getTarget();
13811 if (!lhs_scalar_ty.isSignedInt(mod)) return;
1373713812
1373813813 // If the LHS is widened to a larger integer type, no overflow is possible.
13739 if (lhs_scalar_ty.intInfo(target).bits < resolved_type.intInfo(target).bits) {
13814 if (lhs_scalar_ty.intInfo(mod).bits < resolved_type.intInfo(mod).bits) {
1374013815 return;
1374113816 }
1374213817
13743 const min_int = try resolved_type.minInt(sema.arena, target);
13744 const neg_one_scalar = try Value.Tag.int_i64.create(sema.arena, -1);
13745 const neg_one = if (resolved_type.zigTypeTag() == .Vector)
13746 try Value.Tag.repeated.create(sema.arena, neg_one_scalar)
13747 else
13748 neg_one_scalar;
13818 const min_int = try resolved_type.minInt(mod, resolved_type);
13819 const neg_one_scalar = try mod.intValue(lhs_scalar_ty, -1);
13820 const neg_one = try sema.splat(resolved_type, neg_one_scalar);
1374913821
1375013822 // If the LHS is comptime-known to be not equal to the min int,
1375113823 // no overflow is possible.
1375213824 if (maybe_lhs_val) |lhs_val| {
13753 if (lhs_val.compareAll(.neq, min_int, resolved_type, mod)) return;
13825 if (try lhs_val.compareAll(.neq, min_int, resolved_type, mod)) return;
1375413826 }
1375513827
1375613828 // If the RHS is comptime-known to not be equal to -1, no overflow is possible.
1375713829 if (maybe_rhs_val) |rhs_val| {
13758 if (rhs_val.compareAll(.neq, neg_one, resolved_type, mod)) return;
13830 if (try rhs_val.compareAll(.neq, neg_one, resolved_type, mod)) return;
1375913831 }
1376013832
1376113833 var ok: Air.Inst.Ref = .none;
13762 if (resolved_type.zigTypeTag() == .Vector) {
13834 if (resolved_type.zigTypeTag(mod) == .Vector) {
1376313835 if (maybe_lhs_val == null) {
1376413836 const min_int_ref = try sema.addConstant(resolved_type, min_int);
1376513837 ok = try block.addCmpVector(casted_lhs, min_int_ref, .neq);
......@@ -13815,8 +13887,13 @@ fn addDivByZeroSafety(
1381513887 // emitted above.
1381613888 if (maybe_rhs_val != null) return;
1381713889
13818 const ok = if (resolved_type.zigTypeTag() == .Vector) ok: {
13819 const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
13890 const mod = sema.mod;
13891 const scalar_zero = if (is_int)
13892 try mod.intValue(resolved_type.scalarType(mod), 0)
13893 else
13894 try mod.floatValue(resolved_type.scalarType(mod), 0.0);
13895 const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {
13896 const zero_val = try sema.splat(resolved_type, scalar_zero);
1382013897 const zero = try sema.addConstant(resolved_type, zero_val);
1382113898 const ok = try block.addCmpVector(casted_rhs, zero, .neq);
1382213899 break :ok try block.addInst(.{
......@@ -13827,7 +13904,7 @@ fn addDivByZeroSafety(
1382713904 } },
1382813905 });
1382913906 } else ok: {
13830 const zero = try sema.addConstant(resolved_type, Value.zero);
13907 const zero = try sema.addConstant(resolved_type, scalar_zero);
1383113908 break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
1383213909 };
1383313910 try sema.addSafetyCheck(block, ok, .divide_by_zero);
......@@ -13842,6 +13919,7 @@ fn airTag(block: *Block, is_int: bool, normal: Air.Inst.Tag, optimized: Air.Inst
1384213919}
1384313920
1384413921fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
13922 const mod = sema.mod;
1384513923 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1384613924 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1384713925 sema.src = src;
......@@ -13852,8 +13930,8 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1385213930 const rhs = try sema.resolveInst(extra.rhs);
1385313931 const lhs_ty = sema.typeOf(lhs);
1385413932 const rhs_ty = sema.typeOf(rhs);
13855 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
13856 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
13933 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
13934 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1385713935 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1385813936 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1385913937
......@@ -13862,20 +13940,19 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1386213940 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1386313941 });
1386413942
13865 const is_vector = resolved_type.zigTypeTag() == .Vector;
13943 const is_vector = resolved_type.zigTypeTag(mod) == .Vector;
1386613944
1386713945 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1386813946 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1386913947
13870 const lhs_scalar_ty = lhs_ty.scalarType();
13871 const rhs_scalar_ty = rhs_ty.scalarType();
13872 const scalar_tag = resolved_type.scalarType().zigTypeTag();
13948 const lhs_scalar_ty = lhs_ty.scalarType(mod);
13949 const rhs_scalar_ty = rhs_ty.scalarType(mod);
13950 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1387313951
1387413952 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1387513953
1387613954 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod_rem);
1387713955
13878 const mod = sema.mod;
1387913956 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1388013957 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1388113958
......@@ -13895,20 +13972,26 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1389513972 // then emit a compile error saying you have to pick one.
1389613973 if (is_int) {
1389713974 if (maybe_lhs_val) |lhs_val| {
13898 if (lhs_val.isUndef()) {
13975 if (lhs_val.isUndef(mod)) {
1389913976 return sema.failWithUseOfUndef(block, lhs_src);
1390013977 }
1390113978 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
13902 const zero_val = if (is_vector) b: {
13903 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
13904 } else Value.zero;
13979 const scalar_zero = switch (scalar_tag) {
13980 .ComptimeFloat, .Float => try mod.floatValue(resolved_type.scalarType(mod), 0.0),
13981 .ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
13982 else => unreachable,
13983 };
13984 const zero_val = if (is_vector) (try mod.intern(.{ .aggregate = .{
13985 .ty = resolved_type.toIntern(),
13986 .storage = .{ .repeated_elem = scalar_zero.toIntern() },
13987 } })).toValue() else scalar_zero;
1390513988 return sema.addConstant(resolved_type, zero_val);
1390613989 }
13907 } else if (lhs_scalar_ty.isSignedInt()) {
13990 } else if (lhs_scalar_ty.isSignedInt(mod)) {
1390813991 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
1390913992 }
1391013993 if (maybe_rhs_val) |rhs_val| {
13911 if (rhs_val.isUndef()) {
13994 if (rhs_val.isUndef(mod)) {
1391213995 return sema.failWithUseOfUndef(block, rhs_src);
1391313996 }
1391413997 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -13929,7 +14012,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1392914012 return sema.addConstant(resolved_type, rem_result);
1393014013 }
1393114014 break :rs lhs_src;
13932 } else if (rhs_scalar_ty.isSignedInt()) {
14015 } else if (rhs_scalar_ty.isSignedInt(mod)) {
1393314016 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
1393414017 } else {
1393514018 break :rs rhs_src;
......@@ -13937,7 +14020,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1393714020 }
1393814021 // float operands
1393914022 if (maybe_rhs_val) |rhs_val| {
13940 if (rhs_val.isUndef()) {
14023 if (rhs_val.isUndef(mod)) {
1394114024 return sema.failWithUseOfUndef(block, rhs_src);
1394214025 }
1394314026 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -13947,7 +14030,7 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1394714030 return sema.failWithModRemNegative(block, rhs_src, lhs_ty, rhs_ty);
1394814031 }
1394914032 if (maybe_lhs_val) |lhs_val| {
13950 if (lhs_val.isUndef() or !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))) {
14033 if (lhs_val.isUndef(mod) or !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))) {
1395114034 return sema.failWithModRemNegative(block, lhs_src, lhs_ty, rhs_ty);
1395214035 }
1395314036 return sema.addConstant(
......@@ -13978,32 +14061,31 @@ fn intRem(
1397814061 lhs: Value,
1397914062 rhs: Value,
1398014063) CompileError!Value {
13981 if (ty.zigTypeTag() == .Vector) {
13982 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
14064 const mod = sema.mod;
14065 if (ty.zigTypeTag(mod) == .Vector) {
14066 const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod));
14067 const scalar_ty = ty.scalarType(mod);
1398314068 for (result_data, 0..) |*scalar, i| {
13984 var lhs_buf: Value.ElemValueBuffer = undefined;
13985 var rhs_buf: Value.ElemValueBuffer = undefined;
13986 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
13987 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
13988 scalar.* = try sema.intRemScalar(lhs_elem, rhs_elem);
14069 const lhs_elem = try lhs.elemValue(mod, i);
14070 const rhs_elem = try rhs.elemValue(mod, i);
14071 scalar.* = try (try sema.intRemScalar(lhs_elem, rhs_elem, scalar_ty)).intern(scalar_ty, mod);
1398914072 }
13990 return Value.Tag.aggregate.create(sema.arena, result_data);
14073 return (try mod.intern(.{ .aggregate = .{
14074 .ty = ty.toIntern(),
14075 .storage = .{ .elems = result_data },
14076 } })).toValue();
1399114077 }
13992 return sema.intRemScalar(lhs, rhs);
14078 return sema.intRemScalar(lhs, rhs, ty);
1399314079}
1399414080
13995fn intRemScalar(
13996 sema: *Sema,
13997 lhs: Value,
13998 rhs: Value,
13999) CompileError!Value {
14000 const target = sema.mod.getTarget();
14081fn intRemScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) CompileError!Value {
14082 const mod = sema.mod;
1400114083 // TODO is this a performance issue? maybe we should try the operation without
1400214084 // resorting to BigInt first.
1400314085 var lhs_space: Value.BigIntSpace = undefined;
1400414086 var rhs_space: Value.BigIntSpace = undefined;
14005 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);
14006 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
14087 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
14088 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
1400714089 const limbs_q = try sema.arena.alloc(
1400814090 math.big.Limb,
1400914091 lhs_bigint.limbs.len,
......@@ -14021,10 +14103,11 @@ fn intRemScalar(
1402114103 var result_q = math.big.int.Mutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
1402214104 var result_r = math.big.int.Mutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
1402314105 result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
14024 return Value.fromBigInt(sema.arena, result_r.toConst());
14106 return mod.intValue_big(scalar_ty, result_r.toConst());
1402514107}
1402614108
1402714109fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
14110 const mod = sema.mod;
1402814111 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1402914112 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1403014113 sema.src = src;
......@@ -14035,8 +14118,8 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1403514118 const rhs = try sema.resolveInst(extra.rhs);
1403614119 const lhs_ty = sema.typeOf(lhs);
1403714120 const rhs_ty = sema.typeOf(rhs);
14038 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
14039 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
14121 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
14122 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1404014123 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1404114124 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1404214125
......@@ -14048,13 +14131,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1404814131 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1404914132 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1405014133
14051 const scalar_tag = resolved_type.scalarType().zigTypeTag();
14134 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1405214135
1405314136 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1405414137
1405514138 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .mod);
1405614139
14057 const mod = sema.mod;
1405814140 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1405914141 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1406014142
......@@ -14072,12 +14154,12 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1407214154 // If the lhs is undefined, result is undefined.
1407314155 if (is_int) {
1407414156 if (maybe_lhs_val) |lhs_val| {
14075 if (lhs_val.isUndef()) {
14157 if (lhs_val.isUndef(mod)) {
1407614158 return sema.failWithUseOfUndef(block, lhs_src);
1407714159 }
1407814160 }
1407914161 if (maybe_rhs_val) |rhs_val| {
14080 if (rhs_val.isUndef()) {
14162 if (rhs_val.isUndef(mod)) {
1408114163 return sema.failWithUseOfUndef(block, rhs_src);
1408214164 }
1408314165 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -14096,7 +14178,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1409614178 }
1409714179 // float operands
1409814180 if (maybe_rhs_val) |rhs_val| {
14099 if (rhs_val.isUndef()) {
14181 if (rhs_val.isUndef(mod)) {
1410014182 return sema.failWithUseOfUndef(block, rhs_src);
1410114183 }
1410214184 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -14104,7 +14186,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1410414186 }
1410514187 }
1410614188 if (maybe_lhs_val) |lhs_val| {
14107 if (lhs_val.isUndef()) {
14189 if (lhs_val.isUndef(mod)) {
1410814190 return sema.addConstUndef(resolved_type);
1410914191 }
1411014192 if (maybe_rhs_val) |rhs_val| {
......@@ -14127,6 +14209,7 @@ fn zirMod(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1412714209}
1412814210
1412914211fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
14212 const mod = sema.mod;
1413014213 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1413114214 const src: LazySrcLoc = .{ .node_offset_bin_op = inst_data.src_node };
1413214215 sema.src = src;
......@@ -14137,8 +14220,8 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1413714220 const rhs = try sema.resolveInst(extra.rhs);
1413814221 const lhs_ty = sema.typeOf(lhs);
1413914222 const rhs_ty = sema.typeOf(rhs);
14140 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
14141 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
14223 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
14224 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1414214225 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1414314226 try sema.checkInvalidPtrArithmetic(block, src, lhs_ty);
1414414227
......@@ -14150,13 +14233,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1415014233 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1415114234 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1415214235
14153 const scalar_tag = resolved_type.scalarType().zigTypeTag();
14236 const scalar_tag = resolved_type.scalarType(mod).zigTypeTag(mod);
1415414237
1415514238 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1415614239
1415714240 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, .rem);
1415814241
14159 const mod = sema.mod;
1416014242 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1416114243 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1416214244
......@@ -14174,12 +14256,12 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1417414256 // If the lhs is undefined, result is undefined.
1417514257 if (is_int) {
1417614258 if (maybe_lhs_val) |lhs_val| {
14177 if (lhs_val.isUndef()) {
14259 if (lhs_val.isUndef(mod)) {
1417814260 return sema.failWithUseOfUndef(block, lhs_src);
1417914261 }
1418014262 }
1418114263 if (maybe_rhs_val) |rhs_val| {
14182 if (rhs_val.isUndef()) {
14264 if (rhs_val.isUndef(mod)) {
1418314265 return sema.failWithUseOfUndef(block, rhs_src);
1418414266 }
1418514267 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -14198,7 +14280,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1419814280 }
1419914281 // float operands
1420014282 if (maybe_rhs_val) |rhs_val| {
14201 if (rhs_val.isUndef()) {
14283 if (rhs_val.isUndef(mod)) {
1420214284 return sema.failWithUseOfUndef(block, rhs_src);
1420314285 }
1420414286 if (!(try rhs_val.compareAllWithZeroAdvanced(.neq, sema))) {
......@@ -14206,7 +14288,7 @@ fn zirRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
1420614288 }
1420714289 }
1420814290 if (maybe_lhs_val) |lhs_val| {
14209 if (lhs_val.isUndef()) {
14291 if (lhs_val.isUndef(mod)) {
1421014292 return sema.addConstUndef(resolved_type);
1421114293 }
1421214294 if (maybe_rhs_val) |rhs_val| {
......@@ -14268,7 +14350,7 @@ fn zirOverflowArithmetic(
1426814350 const lhs = try sema.coerce(block, dest_ty, uncasted_lhs, lhs_src);
1426914351 const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);
1427014352
14271 if (dest_ty.scalarType().zigTypeTag() != .Int) {
14353 if (dest_ty.scalarType(mod).zigTypeTag(mod) != .Int) {
1427214354 return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)});
1427314355 }
1427414356
......@@ -14276,30 +14358,32 @@ fn zirOverflowArithmetic(
1427614358 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);
1427714359
1427814360 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
14361 const overflow_ty = mod.intern_pool.indexToKey(tuple_ty.toIntern()).anon_struct_type.types[1].toType();
1427914362
1428014363 var result: struct {
1428114364 inst: Air.Inst.Ref = .none,
14282 wrapped: Value = Value.initTag(.unreachable_value),
14365 wrapped: Value = Value.@"unreachable",
1428314366 overflow_bit: Value,
1428414367 } = result: {
14368 const zero_bit = try mod.intValue(Type.u1, 0);
1428514369 switch (zir_tag) {
1428614370 .add_with_overflow => {
1428714371 // If either of the arguments is zero, `false` is returned and the other is stored
1428814372 // to the result, even if it is undefined..
1428914373 // Otherwise, if either of the argument is undefined, undefined is returned.
1429014374 if (maybe_lhs_val) |lhs_val| {
14291 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14292 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
14375 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14376 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
1429314377 }
1429414378 }
1429514379 if (maybe_rhs_val) |rhs_val| {
14296 if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14297 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
14380 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14381 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
1429814382 }
1429914383 }
1430014384 if (maybe_lhs_val) |lhs_val| {
1430114385 if (maybe_rhs_val) |rhs_val| {
14302 if (lhs_val.isUndef() or rhs_val.isUndef()) {
14386 if (lhs_val.isUndef(mod) or rhs_val.isUndef(mod)) {
1430314387 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
1430414388 }
1430514389
......@@ -14312,12 +14396,12 @@ fn zirOverflowArithmetic(
1431214396 // If the rhs is zero, then the result is lhs and no overflow occured.
1431314397 // Otherwise, if either result is undefined, both results are undefined.
1431414398 if (maybe_rhs_val) |rhs_val| {
14315 if (rhs_val.isUndef()) {
14399 if (rhs_val.isUndef(mod)) {
1431614400 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
1431714401 } else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14318 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
14402 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
1431914403 } else if (maybe_lhs_val) |lhs_val| {
14320 if (lhs_val.isUndef()) {
14404 if (lhs_val.isUndef(mod)) {
1432114405 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
1432214406 }
1432314407
......@@ -14330,29 +14414,30 @@ fn zirOverflowArithmetic(
1433014414 // If either of the arguments is zero, the result is zero and no overflow occured.
1433114415 // If either of the arguments is one, the result is the other and no overflow occured.
1433214416 // Otherwise, if either of the arguments is undefined, both results are undefined.
14417 const scalar_one = try mod.intValue(dest_ty.scalarType(mod), 1);
1433314418 if (maybe_lhs_val) |lhs_val| {
14334 if (!lhs_val.isUndef()) {
14419 if (!lhs_val.isUndef(mod)) {
1433514420 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14336 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
14337 } else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {
14338 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
14421 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
14422 } else if (try sema.compareAll(lhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14423 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
1433914424 }
1434014425 }
1434114426 }
1434214427
1434314428 if (maybe_rhs_val) |rhs_val| {
14344 if (!rhs_val.isUndef()) {
14429 if (!rhs_val.isUndef(mod)) {
1434514430 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14346 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
14347 } else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {
14348 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
14431 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = rhs };
14432 } else if (try sema.compareAll(rhs_val, .eq, try sema.splat(dest_ty, scalar_one), dest_ty)) {
14433 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
1434914434 }
1435014435 }
1435114436 }
1435214437
1435314438 if (maybe_lhs_val) |lhs_val| {
1435414439 if (maybe_rhs_val) |rhs_val| {
14355 if (lhs_val.isUndef() or rhs_val.isUndef()) {
14440 if (lhs_val.isUndef(mod) or rhs_val.isUndef(mod)) {
1435614441 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
1435714442 }
1435814443
......@@ -14366,22 +14451,22 @@ fn zirOverflowArithmetic(
1436614451 // If rhs is zero, the result is lhs (even if undefined) and no overflow occurred.
1436714452 // Oterhwise if either of the arguments is undefined, both results are undefined.
1436814453 if (maybe_lhs_val) |lhs_val| {
14369 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14370 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
14454 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14455 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
1437114456 }
1437214457 }
1437314458 if (maybe_rhs_val) |rhs_val| {
14374 if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14375 break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
14459 if (!rhs_val.isUndef(mod) and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14460 break :result .{ .overflow_bit = try sema.splat(overflow_ty, zero_bit), .inst = lhs };
1437614461 }
1437714462 }
1437814463 if (maybe_lhs_val) |lhs_val| {
1437914464 if (maybe_rhs_val) |rhs_val| {
14380 if (lhs_val.isUndef() or rhs_val.isUndef()) {
14465 if (lhs_val.isUndef(mod) or rhs_val.isUndef(mod)) {
1438114466 break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
1438214467 }
1438314468
14384 const result = try lhs_val.shlWithOverflow(rhs_val, dest_ty, sema.arena, sema.mod);
14469 const result = try lhs_val.shlWithOverflow(rhs_val, dest_ty, sema.arena, mod);
1438514470 break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };
1438614471 }
1438714472 }
......@@ -14420,40 +14505,46 @@ fn zirOverflowArithmetic(
1442014505 }
1442114506
1442214507 if (result.inst == .none) {
14423 const values = try sema.arena.alloc(Value, 2);
14424 values[0] = result.wrapped;
14425 values[1] = result.overflow_bit;
14426 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
14427 return sema.addConstant(tuple_ty, tuple_val);
14508 return sema.addConstant(tuple_ty, (try mod.intern(.{ .aggregate = .{
14509 .ty = tuple_ty.toIntern(),
14510 .storage = .{ .elems = &.{
14511 result.wrapped.toIntern(),
14512 result.overflow_bit.toIntern(),
14513 } },
14514 } })).toValue());
1442814515 }
1442914516
1443014517 const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);
1443114518 element_refs[0] = result.inst;
14432 element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1), result.overflow_bit);
14519 element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1, mod), result.overflow_bit);
1443314520 return block.addAggregateInit(tuple_ty, element_refs);
1443414521}
1443514522
14436fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value {
14437 if (ty.zigTypeTag() != .Vector) return val;
14438 return Value.Tag.repeated.create(sema.arena, val);
14523fn splat(sema: *Sema, ty: Type, val: Value) !Value {
14524 const mod = sema.mod;
14525 if (ty.zigTypeTag(mod) != .Vector) return val;
14526 const repeated = try mod.intern(.{ .aggregate = .{
14527 .ty = ty.toIntern(),
14528 .storage = .{ .repeated_elem = val.toIntern() },
14529 } });
14530 return repeated.toValue();
1443914531}
1444014532
1444114533fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
14442 const ov_ty = if (ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, ty.vectorLen(), Type.u1) else Type.u1;
14443
14444 const types = try sema.arena.alloc(Type, 2);
14445 const values = try sema.arena.alloc(Value, 2);
14446 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
14447 .types = types,
14448 .values = values,
14449 });
14450
14451 types[0] = ty;
14452 types[1] = ov_ty;
14453 values[0] = Value.initTag(.unreachable_value);
14454 values[1] = Value.initTag(.unreachable_value);
14534 const mod = sema.mod;
14535 const ov_ty = if (ty.zigTypeTag(mod) == .Vector) try mod.vectorType(.{
14536 .len = ty.vectorLen(mod),
14537 .child = .u1_type,
14538 }) else Type.u1;
1445514539
14456 return tuple_ty;
14540 const types = [2]InternPool.Index{ ty.toIntern(), ov_ty.toIntern() };
14541 const values = [2]InternPool.Index{ .none, .none };
14542 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
14543 .types = &types,
14544 .values = &values,
14545 .names = &.{},
14546 } });
14547 return tuple_ty.toType();
1445714548}
1445814549
1445914550fn analyzeArithmetic(
......@@ -14468,13 +14559,14 @@ fn analyzeArithmetic(
1446814559 rhs_src: LazySrcLoc,
1446914560 want_safety: bool,
1447014561) CompileError!Air.Inst.Ref {
14562 const mod = sema.mod;
1447114563 const lhs_ty = sema.typeOf(lhs);
1447214564 const rhs_ty = sema.typeOf(rhs);
14473 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
14474 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
14565 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
14566 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
1447514567 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1447614568
14477 if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize()) {
14569 if (lhs_zig_ty_tag == .Pointer) switch (lhs_ty.ptrSize(mod)) {
1447814570 .One, .Slice => {},
1447914571 .Many, .C => {
1448014572 const air_tag: Air.Inst.Tag = switch (zir_tag) {
......@@ -14491,18 +14583,16 @@ fn analyzeArithmetic(
1449114583 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
1449214584 });
1449314585
14494 const is_vector = resolved_type.zigTypeTag() == .Vector;
14495
1449614586 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
1449714587 const casted_rhs = try sema.coerce(block, resolved_type, rhs, rhs_src);
1449814588
14499 const scalar_tag = resolved_type.scalarType().zigTypeTag();
14589 const scalar_type = resolved_type.scalarType(mod);
14590 const scalar_tag = scalar_type.zigTypeTag(mod);
1450014591
1450114592 const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt;
1450214593
1450314594 try sema.checkArithmeticOp(block, src, scalar_tag, lhs_zig_ty_tag, rhs_zig_ty_tag, zir_tag);
1450414595
14505 const mod = sema.mod;
1450614596 const maybe_lhs_val = try sema.resolveMaybeUndefValIntable(casted_lhs);
1450714597 const maybe_rhs_val = try sema.resolveMaybeUndefValIntable(casted_rhs);
1450814598 const rs: struct { src: LazySrcLoc, air_tag: Air.Inst.Tag } = rs: {
......@@ -14516,12 +14606,12 @@ fn analyzeArithmetic(
1451614606 // overflow (max_int), causing illegal behavior.
1451714607 // For floats: either operand being undef makes the result undef.
1451814608 if (maybe_lhs_val) |lhs_val| {
14519 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14609 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
1452014610 return casted_rhs;
1452114611 }
1452214612 }
1452314613 if (maybe_rhs_val) |rhs_val| {
14524 if (rhs_val.isUndef()) {
14614 if (rhs_val.isUndef(mod)) {
1452514615 if (is_int) {
1452614616 return sema.failWithUseOfUndef(block, rhs_src);
1452714617 } else {
......@@ -14534,7 +14624,7 @@ fn analyzeArithmetic(
1453414624 }
1453514625 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .add_optimized else .add;
1453614626 if (maybe_lhs_val) |lhs_val| {
14537 if (lhs_val.isUndef()) {
14627 if (lhs_val.isUndef(mod)) {
1453814628 if (is_int) {
1453914629 return sema.failWithUseOfUndef(block, lhs_src);
1454014630 } else {
......@@ -14543,16 +14633,16 @@ fn analyzeArithmetic(
1454314633 }
1454414634 if (maybe_rhs_val) |rhs_val| {
1454514635 if (is_int) {
14546 const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type);
14547 var vector_index: usize = undefined;
14548 if (!(try sema.intFitsInType(sum, resolved_type, &vector_index))) {
14549 return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vector_index);
14636 var overflow_idx: ?usize = null;
14637 const sum = try sema.intAdd(lhs_val, rhs_val, resolved_type, &overflow_idx);
14638 if (overflow_idx) |vec_idx| {
14639 return sema.failWithIntegerOverflow(block, src, resolved_type, sum, vec_idx);
1455014640 }
1455114641 return sema.addConstant(resolved_type, sum);
1455214642 } else {
1455314643 return sema.addConstant(
1455414644 resolved_type,
14555 try sema.floatAdd(lhs_val, rhs_val, resolved_type),
14645 try Value.floatAdd(lhs_val, rhs_val, resolved_type, sema.arena, mod),
1455614646 );
1455714647 }
1455814648 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
......@@ -14563,13 +14653,13 @@ fn analyzeArithmetic(
1456314653 // If either of the operands are zero, the other operand is returned.
1456414654 // If either of the operands are undefined, the result is undefined.
1456514655 if (maybe_lhs_val) |lhs_val| {
14566 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14656 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
1456714657 return casted_rhs;
1456814658 }
1456914659 }
1457014660 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .addwrap_optimized else .addwrap;
1457114661 if (maybe_rhs_val) |rhs_val| {
14572 if (rhs_val.isUndef()) {
14662 if (rhs_val.isUndef(mod)) {
1457314663 return sema.addConstUndef(resolved_type);
1457414664 }
1457514665 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
......@@ -14588,12 +14678,12 @@ fn analyzeArithmetic(
1458814678 // If either of the operands are zero, then the other operand is returned.
1458914679 // If either of the operands are undefined, the result is undefined.
1459014680 if (maybe_lhs_val) |lhs_val| {
14591 if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
14681 if (!lhs_val.isUndef(mod) and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
1459214682 return casted_rhs;
1459314683 }
1459414684 }
1459514685 if (maybe_rhs_val) |rhs_val| {
14596 if (rhs_val.isUndef()) {
14686 if (rhs_val.isUndef(mod)) {
1459714687 return sema.addConstUndef(resolved_type);
1459814688 }
1459914689 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
......@@ -14601,7 +14691,7 @@ fn analyzeArithmetic(
1460114691 }
1460214692 if (maybe_lhs_val) |lhs_val| {
1460314693 const val = if (scalar_tag == .ComptimeInt)
14604 try sema.intAdd(lhs_val, rhs_val, resolved_type)
14694 try sema.intAdd(lhs_val, rhs_val, resolved_type, undefined)
1460514695 else
1460614696 try lhs_val.intAddSat(rhs_val, resolved_type, sema.arena, mod);
1460714697
......@@ -14618,7 +14708,7 @@ fn analyzeArithmetic(
1461814708 // overflow, causing illegal behavior.
1461914709 // For floats: either operand being undef makes the result undef.
1462014710 if (maybe_rhs_val) |rhs_val| {
14621 if (rhs_val.isUndef()) {
14711 if (rhs_val.isUndef(mod)) {
1462214712 if (is_int) {
1462314713 return sema.failWithUseOfUndef(block, rhs_src);
1462414714 } else {
......@@ -14631,7 +14721,7 @@ fn analyzeArithmetic(
1463114721 }
1463214722 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .sub_optimized else .sub;
1463314723 if (maybe_lhs_val) |lhs_val| {
14634 if (lhs_val.isUndef()) {
14724 if (lhs_val.isUndef(mod)) {
1463514725 if (is_int) {
1463614726 return sema.failWithUseOfUndef(block, lhs_src);
1463714727 } else {
......@@ -14640,16 +14730,16 @@ fn analyzeArithmetic(
1464014730 }
1464114731 if (maybe_rhs_val) |rhs_val| {
1464214732 if (is_int) {
14643 const diff = try sema.intSub(lhs_val, rhs_val, resolved_type);
14644 var vector_index: usize = undefined;
14645 if (!(try sema.intFitsInType(diff, resolved_type, &vector_index))) {
14646 return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vector_index);
14733 var overflow_idx: ?usize = null;
14734 const diff = try sema.intSub(lhs_val, rhs_val, resolved_type, &overflow_idx);
14735 if (overflow_idx) |vec_idx| {
14736 return sema.failWithIntegerOverflow(block, src, resolved_type, diff, vec_idx);
1464714737 }
1464814738 return sema.addConstant(resolved_type, diff);
1464914739 } else {
1465014740 return sema.addConstant(
1465114741 resolved_type,
14652 try sema.floatSub(lhs_val, rhs_val, resolved_type),
14742 try Value.floatSub(lhs_val, rhs_val, resolved_type, sema.arena, mod),
1465314743 );
1465414744 }
1465514745 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
......@@ -14660,7 +14750,7 @@ fn analyzeArithmetic(
1466014750 // If the RHS is zero, then the other operand is returned, even if it is undefined.
1466114751 // If either of the operands are undefined, the result is undefined.
1466214752 if (maybe_rhs_val) |rhs_val| {
14663 if (rhs_val.isUndef()) {
14753 if (rhs_val.isUndef(mod)) {
1466414754 return sema.addConstUndef(resolved_type);
1466514755 }
1466614756 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
......@@ -14669,7 +14759,7 @@ fn analyzeArithmetic(
1466914759 }
1467014760 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .subwrap_optimized else .subwrap;
1467114761 if (maybe_lhs_val) |lhs_val| {
14672 if (lhs_val.isUndef()) {
14762 if (lhs_val.isUndef(mod)) {
1467314763 return sema.addConstUndef(resolved_type);
1467414764 }
1467514765 if (maybe_rhs_val) |rhs_val| {
......@@ -14685,7 +14775,7 @@ fn analyzeArithmetic(
1468514775 // If the RHS is zero, result is LHS.
1468614776 // If either of the operands are undefined, result is undefined.
1468714777 if (maybe_rhs_val) |rhs_val| {
14688 if (rhs_val.isUndef()) {
14778 if (rhs_val.isUndef(mod)) {
1468914779 return sema.addConstUndef(resolved_type);
1469014780 }
1469114781 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
......@@ -14693,12 +14783,12 @@ fn analyzeArithmetic(
1469314783 }
1469414784 }
1469514785 if (maybe_lhs_val) |lhs_val| {
14696 if (lhs_val.isUndef()) {
14786 if (lhs_val.isUndef(mod)) {
1469714787 return sema.addConstUndef(resolved_type);
1469814788 }
1469914789 if (maybe_rhs_val) |rhs_val| {
1470014790 const val = if (scalar_tag == .ComptimeInt)
14701 try sema.intSub(lhs_val, rhs_val, resolved_type)
14791 try sema.intSub(lhs_val, rhs_val, resolved_type, undefined)
1470214792 else
1470314793 try lhs_val.intSubSat(rhs_val, resolved_type, sema.arena, mod);
1470414794
......@@ -14718,62 +14808,74 @@ fn analyzeArithmetic(
1471814808 // If either of the operands are inf, and the other operand is zero,
1471914809 // the result is nan.
1472014810 // If either of the operands are nan, the result is nan.
14811 const scalar_zero = switch (scalar_tag) {
14812 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 0.0),
14813 .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
14814 else => unreachable,
14815 };
14816 const scalar_one = switch (scalar_tag) {
14817 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 1.0),
14818 .ComptimeInt, .Int => try mod.intValue(scalar_type, 1),
14819 else => unreachable,
14820 };
1472114821 if (maybe_lhs_val) |lhs_val| {
14722 if (!lhs_val.isUndef()) {
14723 if (lhs_val.isNan()) {
14822 if (!lhs_val.isUndef(mod)) {
14823 if (lhs_val.isNan(mod)) {
1472414824 return sema.addConstant(resolved_type, lhs_val);
1472514825 }
1472614826 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) lz: {
1472714827 if (maybe_rhs_val) |rhs_val| {
14728 if (rhs_val.isNan()) {
14828 if (rhs_val.isNan(mod)) {
1472914829 return sema.addConstant(resolved_type, rhs_val);
1473014830 }
14731 if (rhs_val.isInf()) {
14732 return sema.addConstant(resolved_type, try Value.Tag.float_32.create(sema.arena, std.math.nan_f32));
14831 if (rhs_val.isInf(mod)) {
14832 return sema.addConstant(
14833 resolved_type,
14834 try mod.floatValue(resolved_type, std.math.nan_f128),
14835 );
1473314836 }
1473414837 } else if (resolved_type.isAnyFloat()) {
1473514838 break :lz;
1473614839 }
14737 const zero_val = if (is_vector) b: {
14738 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14739 } else Value.zero;
14840 const zero_val = try sema.splat(resolved_type, scalar_zero);
1474014841 return sema.addConstant(resolved_type, zero_val);
1474114842 }
14742 if (try sema.compareAll(lhs_val, .eq, Value.one, resolved_type)) {
14843 if (try sema.compareAll(lhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
1474314844 return casted_rhs;
1474414845 }
1474514846 }
1474614847 }
1474714848 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mul_optimized else .mul;
1474814849 if (maybe_rhs_val) |rhs_val| {
14749 if (rhs_val.isUndef()) {
14850 if (rhs_val.isUndef(mod)) {
1475014851 if (is_int) {
1475114852 return sema.failWithUseOfUndef(block, rhs_src);
1475214853 } else {
1475314854 return sema.addConstUndef(resolved_type);
1475414855 }
1475514856 }
14756 if (rhs_val.isNan()) {
14857 if (rhs_val.isNan(mod)) {
1475714858 return sema.addConstant(resolved_type, rhs_val);
1475814859 }
1475914860 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) rz: {
1476014861 if (maybe_lhs_val) |lhs_val| {
14761 if (lhs_val.isInf()) {
14762 return sema.addConstant(resolved_type, try Value.Tag.float_32.create(sema.arena, std.math.nan_f32));
14862 if (lhs_val.isInf(mod)) {
14863 return sema.addConstant(
14864 resolved_type,
14865 try mod.floatValue(resolved_type, std.math.nan_f128),
14866 );
1476314867 }
1476414868 } else if (resolved_type.isAnyFloat()) {
1476514869 break :rz;
1476614870 }
14767 const zero_val = if (is_vector) b: {
14768 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14769 } else Value.zero;
14871 const zero_val = try sema.splat(resolved_type, scalar_zero);
1477014872 return sema.addConstant(resolved_type, zero_val);
1477114873 }
14772 if (try sema.compareAll(rhs_val, .eq, Value.one, resolved_type)) {
14874 if (try sema.compareAll(rhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
1477314875 return casted_lhs;
1477414876 }
1477514877 if (maybe_lhs_val) |lhs_val| {
14776 if (lhs_val.isUndef()) {
14878 if (lhs_val.isUndef(mod)) {
1477714879 if (is_int) {
1477814880 return sema.failWithUseOfUndef(block, lhs_src);
1477914881 } else {
......@@ -14781,16 +14883,16 @@ fn analyzeArithmetic(
1478114883 }
1478214884 }
1478314885 if (is_int) {
14784 const product = try lhs_val.intMul(rhs_val, resolved_type, sema.arena, sema.mod);
14785 var vector_index: usize = undefined;
14786 if (!(try sema.intFitsInType(product, resolved_type, &vector_index))) {
14787 return sema.failWithIntegerOverflow(block, src, resolved_type, product, vector_index);
14886 var overflow_idx: ?usize = null;
14887 const product = try lhs_val.intMul(rhs_val, resolved_type, &overflow_idx, sema.arena, mod);
14888 if (overflow_idx) |vec_idx| {
14889 return sema.failWithIntegerOverflow(block, src, resolved_type, product, vec_idx);
1478814890 }
1478914891 return sema.addConstant(resolved_type, product);
1479014892 } else {
1479114893 return sema.addConstant(
1479214894 resolved_type,
14793 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, sema.mod),
14895 try lhs_val.floatMul(rhs_val, resolved_type, sema.arena, mod),
1479414896 );
1479514897 }
1479614898 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
......@@ -14801,40 +14903,46 @@ fn analyzeArithmetic(
1480114903 // If either of the operands are zero, result is zero.
1480214904 // If either of the operands are one, result is the other operand.
1480314905 // If either of the operands are undefined, result is undefined.
14906 const scalar_zero = switch (scalar_tag) {
14907 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 0.0),
14908 .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
14909 else => unreachable,
14910 };
14911 const scalar_one = switch (scalar_tag) {
14912 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 1.0),
14913 .ComptimeInt, .Int => try mod.intValue(scalar_type, 1),
14914 else => unreachable,
14915 };
1480414916 if (maybe_lhs_val) |lhs_val| {
14805 if (!lhs_val.isUndef()) {
14917 if (!lhs_val.isUndef(mod)) {
1480614918 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14807 const zero_val = if (is_vector) b: {
14808 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14809 } else Value.zero;
14919 const zero_val = try sema.splat(resolved_type, scalar_zero);
1481014920 return sema.addConstant(resolved_type, zero_val);
1481114921 }
14812 if (try sema.compareAll(lhs_val, .eq, Value.one, resolved_type)) {
14922 if (try sema.compareAll(lhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
1481314923 return casted_rhs;
1481414924 }
1481514925 }
1481614926 }
1481714927 const air_tag: Air.Inst.Tag = if (block.float_mode == .Optimized) .mulwrap_optimized else .mulwrap;
1481814928 if (maybe_rhs_val) |rhs_val| {
14819 if (rhs_val.isUndef()) {
14929 if (rhs_val.isUndef(mod)) {
1482014930 return sema.addConstUndef(resolved_type);
1482114931 }
1482214932 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14823 const zero_val = if (is_vector) b: {
14824 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14825 } else Value.zero;
14933 const zero_val = try sema.splat(resolved_type, scalar_zero);
1482614934 return sema.addConstant(resolved_type, zero_val);
1482714935 }
14828 if (try sema.compareAll(rhs_val, .eq, Value.one, resolved_type)) {
14936 if (try sema.compareAll(rhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
1482914937 return casted_lhs;
1483014938 }
1483114939 if (maybe_lhs_val) |lhs_val| {
14832 if (lhs_val.isUndef()) {
14940 if (lhs_val.isUndef(mod)) {
1483314941 return sema.addConstUndef(resolved_type);
1483414942 }
1483514943 return sema.addConstant(
1483614944 resolved_type,
14837 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, sema.mod),
14945 try lhs_val.numberMulWrap(rhs_val, resolved_type, sema.arena, mod),
1483814946 );
1483914947 } else break :rs .{ .src = lhs_src, .air_tag = air_tag };
1484014948 } else break :rs .{ .src = rhs_src, .air_tag = air_tag };
......@@ -14844,41 +14952,47 @@ fn analyzeArithmetic(
1484414952 // If either of the operands are zero, result is zero.
1484514953 // If either of the operands are one, result is the other operand.
1484614954 // If either of the operands are undefined, result is undefined.
14955 const scalar_zero = switch (scalar_tag) {
14956 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 0.0),
14957 .ComptimeInt, .Int => try mod.intValue(scalar_type, 0),
14958 else => unreachable,
14959 };
14960 const scalar_one = switch (scalar_tag) {
14961 .ComptimeFloat, .Float => try mod.floatValue(scalar_type, 1.0),
14962 .ComptimeInt, .Int => try mod.intValue(scalar_type, 1),
14963 else => unreachable,
14964 };
1484714965 if (maybe_lhs_val) |lhs_val| {
14848 if (!lhs_val.isUndef()) {
14966 if (!lhs_val.isUndef(mod)) {
1484914967 if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14850 const zero_val = if (is_vector) b: {
14851 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14852 } else Value.zero;
14968 const zero_val = try sema.splat(resolved_type, scalar_zero);
1485314969 return sema.addConstant(resolved_type, zero_val);
1485414970 }
14855 if (try sema.compareAll(lhs_val, .eq, Value.one, resolved_type)) {
14971 if (try sema.compareAll(lhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
1485614972 return casted_rhs;
1485714973 }
1485814974 }
1485914975 }
1486014976 if (maybe_rhs_val) |rhs_val| {
14861 if (rhs_val.isUndef()) {
14977 if (rhs_val.isUndef(mod)) {
1486214978 return sema.addConstUndef(resolved_type);
1486314979 }
1486414980 if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
14865 const zero_val = if (is_vector) b: {
14866 break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
14867 } else Value.zero;
14981 const zero_val = try sema.splat(resolved_type, scalar_zero);
1486814982 return sema.addConstant(resolved_type, zero_val);
1486914983 }
14870 if (try sema.compareAll(rhs_val, .eq, Value.one, resolved_type)) {
14984 if (try sema.compareAll(rhs_val, .eq, try sema.splat(resolved_type, scalar_one), resolved_type)) {
1487114985 return casted_lhs;
1487214986 }
1487314987 if (maybe_lhs_val) |lhs_val| {
14874 if (lhs_val.isUndef()) {
14988 if (lhs_val.isUndef(mod)) {
1487514989 return sema.addConstUndef(resolved_type);
1487614990 }
1487714991
1487814992 const val = if (scalar_tag == .ComptimeInt)
14879 try lhs_val.intMul(rhs_val, resolved_type, sema.arena, sema.mod)
14993 try lhs_val.intMul(rhs_val, resolved_type, undefined, sema.arena, mod)
1488014994 else
14881 try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, sema.mod);
14995 try lhs_val.intMulSat(rhs_val, resolved_type, sema.arena, mod);
1488214996
1488314997 return sema.addConstant(resolved_type, val);
1488414998 } else break :rs .{ .src = lhs_src, .air_tag = .mul_sat };
......@@ -14910,7 +15024,7 @@ fn analyzeArithmetic(
1491015024 } },
1491115025 });
1491215026 const ov_bit = try sema.tupleFieldValByIndex(block, src, op_ov, 1, op_ov_tuple_ty);
14913 const any_ov_bit = if (resolved_type.zigTypeTag() == .Vector)
15027 const any_ov_bit = if (resolved_type.zigTypeTag(mod) == .Vector)
1491415028 try block.addInst(.{
1491515029 .tag = if (block.float_mode == .Optimized) .reduce_optimized else .reduce,
1491615030 .data = .{ .reduce = .{
......@@ -14920,7 +15034,7 @@ fn analyzeArithmetic(
1492015034 })
1492115035 else
1492215036 ov_bit;
14923 const zero_ov = try sema.addConstant(Type.u1, Value.zero);
15037 const zero_ov = try sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
1492415038 const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
1492515039
1492615040 try sema.addSafetyCheck(block, no_ov, .integer_overflow);
......@@ -14944,15 +15058,12 @@ fn analyzePtrArithmetic(
1494415058 // TODO if the operand is comptime-known to be negative, or is a negative int,
1494515059 // coerce to isize instead of usize.
1494615060 const offset = try sema.coerce(block, Type.usize, uncasted_offset, offset_src);
14947 const target = sema.mod.getTarget();
15061 const mod = sema.mod;
1494815062 const opt_ptr_val = try sema.resolveMaybeUndefVal(ptr);
1494915063 const opt_off_val = try sema.resolveDefinedValue(block, offset_src, offset);
1495015064 const ptr_ty = sema.typeOf(ptr);
14951 const ptr_info = ptr_ty.ptrInfo().data;
14952 const elem_ty = if (ptr_info.size == .One and ptr_info.pointee_type.zigTypeTag() == .Array)
14953 ptr_info.pointee_type.childType()
14954 else
14955 ptr_info.pointee_type;
15065 const ptr_info = ptr_ty.ptrInfo(mod);
15066 assert(ptr_info.size == .Many or ptr_info.size == .C);
1495615067
1495715068 const new_ptr_ty = t: {
1495815069 // Calculate the new pointer alignment.
......@@ -14963,9 +15074,9 @@ fn analyzePtrArithmetic(
1496315074 }
1496415075 // If the addend is not a comptime-known value we can still count on
1496515076 // it being a multiple of the type size.
14966 const elem_size = elem_ty.abiSize(target);
15077 const elem_size = ptr_info.pointee_type.abiSize(mod);
1496715078 const addend = if (opt_off_val) |off_val| a: {
14968 const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(target));
15079 const off_int = try sema.usizeCast(block, offset_src, off_val.toUnsignedInt(mod));
1496915080 break :a elem_size * off_int;
1497015081 } else elem_size;
1497115082
......@@ -14974,7 +15085,7 @@ fn analyzePtrArithmetic(
1497415085 // non zero).
1497515086 const new_align = @as(u32, 1) << @intCast(u5, @ctz(addend | ptr_info.@"align"));
1497615087
14977 break :t try Type.ptr(sema.arena, sema.mod, .{
15088 break :t try Type.ptr(sema.arena, mod, .{
1497815089 .pointee_type = ptr_info.pointee_type,
1497915090 .sentinel = ptr_info.sentinel,
1498015091 .@"align" = new_align,
......@@ -14989,24 +15100,24 @@ fn analyzePtrArithmetic(
1498915100 const runtime_src = rs: {
1499015101 if (opt_ptr_val) |ptr_val| {
1499115102 if (opt_off_val) |offset_val| {
14992 if (ptr_val.isUndef()) return sema.addConstUndef(new_ptr_ty);
15103 if (ptr_val.isUndef(mod)) return sema.addConstUndef(new_ptr_ty);
1499315104
14994 const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(target));
15105 const offset_int = try sema.usizeCast(block, offset_src, offset_val.toUnsignedInt(mod));
1499515106 if (offset_int == 0) return ptr;
14996 if (try ptr_val.getUnsignedIntAdvanced(target, sema)) |addr| {
14997 const elem_size = elem_ty.abiSize(target);
15107 if (try ptr_val.getUnsignedIntAdvanced(mod, sema)) |addr| {
15108 const elem_size = ptr_info.pointee_type.abiSize(mod);
1499815109 const new_addr = switch (air_tag) {
1499915110 .ptr_add => addr + elem_size * offset_int,
1500015111 .ptr_sub => addr - elem_size * offset_int,
1500115112 else => unreachable,
1500215113 };
15003 const new_ptr_val = try Value.Tag.int_u64.create(sema.arena, new_addr);
15114 const new_ptr_val = try mod.ptrIntValue(new_ptr_ty, new_addr);
1500415115 return sema.addConstant(new_ptr_ty, new_ptr_val);
1500515116 }
1500615117 if (air_tag == .ptr_sub) {
1500715118 return sema.fail(block, op_src, "TODO implement Sema comptime pointer subtraction", .{});
1500815119 }
15009 const new_ptr_val = try ptr_val.elemPtr(ptr_ty, sema.arena, offset_int, sema.mod);
15120 const new_ptr_val = try ptr_val.elemPtr(new_ptr_ty, offset_int, mod);
1501015121 return sema.addConstant(new_ptr_ty, new_ptr_val);
1501115122 } else break :rs offset_src;
1501215123 } else break :rs ptr_src;
......@@ -15052,7 +15163,7 @@ fn zirAsm(
1505215163 const inputs_len = @truncate(u5, extended.small >> 5);
1505315164 const clobbers_len = @truncate(u5, extended.small >> 10);
1505415165 const is_volatile = @truncate(u1, extended.small >> 15) != 0;
15055 const is_global_assembly = sema.func == null;
15166 const is_global_assembly = sema.func_index == .none;
1505615167
1505715168 const asm_source: []const u8 = if (tmpl_is_expr) blk: {
1505815169 const tmpl = @intToEnum(Zir.Inst.Ref, extra.data.asm_source);
......@@ -15116,6 +15227,7 @@ fn zirAsm(
1511615227
1511715228 const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len);
1511815229 const inputs = try sema.arena.alloc(ConstraintName, inputs_len);
15230 const mod = sema.mod;
1511915231
1512015232 for (args, 0..) |*arg, arg_i| {
1512115233 const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
......@@ -15123,9 +15235,9 @@ fn zirAsm(
1512315235
1512415236 const uncasted_arg = try sema.resolveInst(input.data.operand);
1512515237 const uncasted_arg_ty = sema.typeOf(uncasted_arg);
15126 switch (uncasted_arg_ty.zigTypeTag()) {
15127 .ComptimeInt => arg.* = try sema.coerce(block, Type.initTag(.usize), uncasted_arg, src),
15128 .ComptimeFloat => arg.* = try sema.coerce(block, Type.initTag(.f64), uncasted_arg, src),
15238 switch (uncasted_arg_ty.zigTypeTag(mod)) {
15239 .ComptimeInt => arg.* = try sema.coerce(block, Type.usize, uncasted_arg, src),
15240 .ComptimeFloat => arg.* = try sema.coerce(block, Type.f64, uncasted_arg, src),
1512915241 else => {
1513015242 arg.* = uncasted_arg;
1513115243 try sema.queueFullTypeResolution(uncasted_arg_ty);
......@@ -15205,6 +15317,7 @@ fn zirCmpEq(
1520515317 const tracy = trace(@src());
1520615318 defer tracy.end();
1520715319
15320 const mod = sema.mod;
1520815321 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1520915322 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1521015323 const src: LazySrcLoc = inst_data.src();
......@@ -15215,8 +15328,8 @@ fn zirCmpEq(
1521515328
1521615329 const lhs_ty = sema.typeOf(lhs);
1521715330 const rhs_ty = sema.typeOf(rhs);
15218 const lhs_ty_tag = lhs_ty.zigTypeTag();
15219 const rhs_ty_tag = rhs_ty.zigTypeTag();
15331 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
15332 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
1522015333 if (lhs_ty_tag == .Null and rhs_ty_tag == .Null) {
1522115334 // null == null, null != null
1522215335 if (op == .eq) {
......@@ -15227,16 +15340,16 @@ fn zirCmpEq(
1522715340 }
1522815341
1522915342 // comparing null with optionals
15230 if (lhs_ty_tag == .Null and (rhs_ty_tag == .Optional or rhs_ty.isCPtr())) {
15343 if (lhs_ty_tag == .Null and (rhs_ty_tag == .Optional or rhs_ty.isCPtr(mod))) {
1523115344 return sema.analyzeIsNull(block, src, rhs, op == .neq);
1523215345 }
15233 if (rhs_ty_tag == .Null and (lhs_ty_tag == .Optional or lhs_ty.isCPtr())) {
15346 if (rhs_ty_tag == .Null and (lhs_ty_tag == .Optional or lhs_ty.isCPtr(mod))) {
1523415347 return sema.analyzeIsNull(block, src, lhs, op == .neq);
1523515348 }
1523615349
1523715350 if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) {
1523815351 const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty;
15239 return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type.fmt(sema.mod)});
15352 return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type.fmt(mod)});
1524015353 }
1524115354
1524215355 if (lhs_ty_tag == .Union and (rhs_ty_tag == .EnumLiteral or rhs_ty_tag == .Enum)) {
......@@ -15250,15 +15363,12 @@ fn zirCmpEq(
1525015363 const runtime_src: LazySrcLoc = src: {
1525115364 if (try sema.resolveMaybeUndefVal(lhs)) |lval| {
1525215365 if (try sema.resolveMaybeUndefVal(rhs)) |rval| {
15253 if (lval.isUndef() or rval.isUndef()) {
15366 if (lval.isUndef(mod) or rval.isUndef(mod)) {
1525415367 return sema.addConstUndef(Type.bool);
1525515368 }
15256 // TODO optimisation opportunity: evaluate if mem.eql is faster with the names,
15257 // or calling to Module.getErrorValue to get the values and then compare them is
15258 // faster.
15259 const lhs_name = lval.castTag(.@"error").?.data.name;
15260 const rhs_name = rval.castTag(.@"error").?.data.name;
15261 if (mem.eql(u8, lhs_name, rhs_name) == (op == .eq)) {
15369 const lkey = mod.intern_pool.indexToKey(lval.toIntern());
15370 const rkey = mod.intern_pool.indexToKey(rval.toIntern());
15371 if ((lkey.err.name == rkey.err.name) == (op == .eq)) {
1526215372 return Air.Inst.Ref.bool_true;
1526315373 } else {
1526415374 return Air.Inst.Ref.bool_false;
......@@ -15276,7 +15386,7 @@ fn zirCmpEq(
1527615386 if (lhs_ty_tag == .Type and rhs_ty_tag == .Type) {
1527715387 const lhs_as_type = try sema.analyzeAsType(block, lhs_src, lhs);
1527815388 const rhs_as_type = try sema.analyzeAsType(block, rhs_src, rhs);
15279 if (lhs_as_type.eql(rhs_as_type, sema.mod) == (op == .eq)) {
15389 if (lhs_as_type.eql(rhs_as_type, mod) == (op == .eq)) {
1528015390 return Air.Inst.Ref.bool_true;
1528115391 } else {
1528215392 return Air.Inst.Ref.bool_false;
......@@ -15295,12 +15405,13 @@ fn analyzeCmpUnionTag(
1529515405 tag_src: LazySrcLoc,
1529615406 op: std.math.CompareOperator,
1529715407) CompileError!Air.Inst.Ref {
15408 const mod = sema.mod;
1529815409 const union_ty = try sema.resolveTypeFields(sema.typeOf(un));
15299 const union_tag_ty = union_ty.unionTagType() orelse {
15410 const union_tag_ty = union_ty.unionTagType(mod) orelse {
1530015411 const msg = msg: {
1530115412 const msg = try sema.errMsg(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{});
1530215413 errdefer msg.destroy(sema.gpa);
15303 try sema.mod.errNoteNonLazy(union_ty.declSrcLoc(sema.mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(sema.mod)});
15414 try mod.errNoteNonLazy(union_ty.declSrcLoc(mod), msg, "union '{}' is not a tagged union", .{union_ty.fmt(mod)});
1530415415 break :msg msg;
1530515416 };
1530615417 return sema.failWithOwnedErrorMsg(msg);
......@@ -15311,9 +15422,9 @@ fn analyzeCmpUnionTag(
1531115422 const coerced_union = try sema.coerce(block, union_tag_ty, un, un_src);
1531215423
1531315424 if (try sema.resolveMaybeUndefVal(coerced_tag)) |enum_val| {
15314 if (enum_val.isUndef()) return sema.addConstUndef(Type.bool);
15315 const field_ty = union_ty.unionFieldType(enum_val, sema.mod);
15316 if (field_ty.zigTypeTag() == .NoReturn) {
15425 if (enum_val.isUndef(mod)) return sema.addConstUndef(Type.bool);
15426 const field_ty = union_ty.unionFieldType(enum_val, mod);
15427 if (field_ty.zigTypeTag(mod) == .NoReturn) {
1531715428 return Air.Inst.Ref.bool_false;
1531815429 }
1531915430 }
......@@ -15352,34 +15463,35 @@ fn analyzeCmp(
1535215463 rhs_src: LazySrcLoc,
1535315464 is_equality_cmp: bool,
1535415465) CompileError!Air.Inst.Ref {
15466 const mod = sema.mod;
1535515467 const lhs_ty = sema.typeOf(lhs);
1535615468 const rhs_ty = sema.typeOf(rhs);
15357 if (lhs_ty.zigTypeTag() != .Optional and rhs_ty.zigTypeTag() != .Optional) {
15469 if (lhs_ty.zigTypeTag(mod) != .Optional and rhs_ty.zigTypeTag(mod) != .Optional) {
1535815470 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
1535915471 }
1536015472
15361 if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) {
15473 if (lhs_ty.zigTypeTag(mod) == .Vector and rhs_ty.zigTypeTag(mod) == .Vector) {
1536215474 return sema.cmpVector(block, src, lhs, rhs, op, lhs_src, rhs_src);
1536315475 }
15364 if (lhs_ty.isNumeric() and rhs_ty.isNumeric()) {
15476 if (lhs_ty.isNumeric(mod) and rhs_ty.isNumeric(mod)) {
1536515477 // This operation allows any combination of integer and float types, regardless of the
1536615478 // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for
1536715479 // numeric types.
1536815480 return sema.cmpNumeric(block, src, lhs, rhs, op, lhs_src, rhs_src);
1536915481 }
15370 if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorUnion and rhs_ty.zigTypeTag() == .ErrorSet) {
15482 if (is_equality_cmp and lhs_ty.zigTypeTag(mod) == .ErrorUnion and rhs_ty.zigTypeTag(mod) == .ErrorSet) {
1537115483 const casted_lhs = try sema.analyzeErrUnionCode(block, lhs_src, lhs);
1537215484 return sema.cmpSelf(block, src, casted_lhs, rhs, op, lhs_src, rhs_src);
1537315485 }
15374 if (is_equality_cmp and lhs_ty.zigTypeTag() == .ErrorSet and rhs_ty.zigTypeTag() == .ErrorUnion) {
15486 if (is_equality_cmp and lhs_ty.zigTypeTag(mod) == .ErrorSet and rhs_ty.zigTypeTag(mod) == .ErrorUnion) {
1537515487 const casted_rhs = try sema.analyzeErrUnionCode(block, rhs_src, rhs);
1537615488 return sema.cmpSelf(block, src, lhs, casted_rhs, op, lhs_src, rhs_src);
1537715489 }
1537815490 const instructions = &[_]Air.Inst.Ref{ lhs, rhs };
1537915491 const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]?LazySrcLoc{ lhs_src, rhs_src } });
15380 if (!resolved_type.isSelfComparable(is_equality_cmp)) {
15492 if (!resolved_type.isSelfComparable(mod, is_equality_cmp)) {
1538115493 return sema.fail(block, src, "operator {s} not allowed for type '{}'", .{
15382 compareOperatorName(op), resolved_type.fmt(sema.mod),
15494 compareOperatorName(op), resolved_type.fmt(mod),
1538315495 });
1538415496 }
1538515497 const casted_lhs = try sema.coerce(block, resolved_type, lhs, lhs_src);
......@@ -15408,15 +15520,19 @@ fn cmpSelf(
1540815520 lhs_src: LazySrcLoc,
1540915521 rhs_src: LazySrcLoc,
1541015522) CompileError!Air.Inst.Ref {
15523 const mod = sema.mod;
1541115524 const resolved_type = sema.typeOf(casted_lhs);
1541215525 const runtime_src: LazySrcLoc = src: {
1541315526 if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| {
15414 if (lhs_val.isUndef()) return sema.addConstUndef(Type.bool);
15527 if (lhs_val.isUndef(mod)) return sema.addConstUndef(Type.bool);
1541515528 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {
15416 if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool);
15529 if (rhs_val.isUndef(mod)) return sema.addConstUndef(Type.bool);
1541715530
15418 if (resolved_type.zigTypeTag() == .Vector) {
15419 const result_ty = try Type.vector(sema.arena, resolved_type.vectorLen(), Type.bool);
15531 if (resolved_type.zigTypeTag(mod) == .Vector) {
15532 const result_ty = try mod.vectorType(.{
15533 .len = resolved_type.vectorLen(mod),
15534 .child = .bool_type,
15535 });
1542015536 const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_type);
1542115537 return sema.addConstant(result_ty, cmp_val);
1542215538 }
......@@ -15427,7 +15543,7 @@ fn cmpSelf(
1542715543 return Air.Inst.Ref.bool_false;
1542815544 }
1542915545 } else {
15430 if (resolved_type.zigTypeTag() == .Bool) {
15546 if (resolved_type.zigTypeTag(mod) == .Bool) {
1543115547 // We can lower bool eq/neq more efficiently.
1543215548 return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src);
1543315549 }
......@@ -15436,9 +15552,9 @@ fn cmpSelf(
1543615552 } else {
1543715553 // For bools, we still check the other operand, because we can lower
1543815554 // bool eq/neq more efficiently.
15439 if (resolved_type.zigTypeTag() == .Bool) {
15555 if (resolved_type.zigTypeTag(mod) == .Bool) {
1544015556 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {
15441 if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool);
15557 if (rhs_val.isUndef(mod)) return sema.addConstUndef(Type.bool);
1544215558 return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src);
1544315559 }
1544415560 }
......@@ -15446,7 +15562,7 @@ fn cmpSelf(
1544615562 }
1544715563 };
1544815564 try sema.requireRuntimeBlock(block, src, runtime_src);
15449 if (resolved_type.zigTypeTag() == .Vector) {
15565 if (resolved_type.zigTypeTag(mod) == .Vector) {
1545015566 return block.addCmpVector(casted_lhs, casted_rhs, op);
1545115567 }
1545215568 const tag = Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized);
......@@ -15475,16 +15591,17 @@ fn runtimeBoolCmp(
1547515591}
1547615592
1547715593fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15594 const mod = sema.mod;
1547815595 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1547915596 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1548015597 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
15481 switch (ty.zigTypeTag()) {
15598 switch (ty.zigTypeTag(mod)) {
1548215599 .Fn,
1548315600 .NoReturn,
1548415601 .Undefined,
1548515602 .Null,
1548615603 .Opaque,
15487 => return sema.fail(block, operand_src, "no size available for type '{}'", .{ty.fmt(sema.mod)}),
15604 => return sema.fail(block, operand_src, "no size available for type '{}'", .{ty.fmt(mod)}),
1548815605
1548915606 .Type,
1549015607 .EnumLiteral,
......@@ -15509,25 +15626,25 @@ fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
1550915626 .AnyFrame,
1551015627 => {},
1551115628 }
15512 const target = sema.mod.getTarget();
15513 const val = try ty.lazyAbiSize(target, sema.arena);
15514 if (val.tag() == .lazy_size) {
15629 const val = try ty.lazyAbiSize(mod);
15630 if (val.isLazySize(mod)) {
1551515631 try sema.queueFullTypeResolution(ty);
1551615632 }
1551715633 return sema.addConstant(Type.comptime_int, val);
1551815634}
1551915635
1552015636fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15637 const mod = sema.mod;
1552115638 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1552215639 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1552315640 const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand);
15524 switch (operand_ty.zigTypeTag()) {
15641 switch (operand_ty.zigTypeTag(mod)) {
1552515642 .Fn,
1552615643 .NoReturn,
1552715644 .Undefined,
1552815645 .Null,
1552915646 .Opaque,
15530 => return sema.fail(block, operand_src, "no size available for type '{}'", .{operand_ty.fmt(sema.mod)}),
15647 => return sema.fail(block, operand_src, "no size available for type '{}'", .{operand_ty.fmt(mod)}),
1553115648
1553215649 .Type,
1553315650 .EnumLiteral,
......@@ -15552,8 +15669,7 @@ fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1555215669 .AnyFrame,
1555315670 => {},
1555415671 }
15555 const target = sema.mod.getTarget();
15556 const bit_size = try operand_ty.bitSizeAdvanced(target, sema);
15672 const bit_size = try operand_ty.bitSizeAdvanced(mod, sema);
1555715673 return sema.addIntUnsigned(Type.comptime_int, bit_size);
1555815674}
1555915675
......@@ -15562,17 +15678,13 @@ fn zirThis(
1556215678 block: *Block,
1556315679 extended: Zir.Inst.Extended.InstData,
1556415680) CompileError!Air.Inst.Ref {
15565 const this_decl_index = block.namespace.getDeclIndex();
15681 const mod = sema.mod;
15682 const this_decl_index = mod.namespaceDeclIndex(block.namespace);
1556615683 const src = LazySrcLoc.nodeOffset(@bitCast(i32, extended.operand));
1556715684 return sema.analyzeDeclVal(block, src, this_decl_index);
1556815685}
1556915686
15570fn zirClosureCapture(
15571 sema: *Sema,
15572 block: *Block,
15573 inst: Zir.Inst.Index,
15574) CompileError!void {
15575 // TODO: Compile error when closed over values are modified
15687fn zirClosureCapture(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
1557615688 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
1557715689 // Closures are not necessarily constant values. For example, the
1557815690 // code might do something like this:
......@@ -15580,26 +15692,24 @@ fn zirClosureCapture(
1558015692 // ...in which case the closure_capture instruction has access to a runtime
1558115693 // value only. In such case we preserve the type and use a dummy runtime value.
1558215694 const operand = try sema.resolveInst(inst_data.operand);
15583 const val = (try sema.resolveMaybeUndefValAllowVariables(operand)) orelse
15584 Value.initTag(.unreachable_value);
15585
15586 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, .{
15587 .ty = try sema.typeOf(operand).copy(sema.perm_arena),
15588 .val = try val.copy(sema.perm_arena),
15589 });
15695 const ty = sema.typeOf(operand);
15696 const capture: CaptureScope.Capture = blk: {
15697 if (try sema.resolveMaybeUndefValAllowVariables(operand)) |val| {
15698 const ip_index = try val.intern(ty, sema.mod);
15699 break :blk .{ .comptime_val = ip_index };
15700 }
15701 break :blk .{ .runtime_val = ty.toIntern() };
15702 };
15703 try block.wip_capture_scope.captures.putNoClobber(sema.gpa, inst, capture);
1559015704}
1559115705
15592fn zirClosureGet(
15593 sema: *Sema,
15594 block: *Block,
15595 inst: Zir.Inst.Index,
15596) CompileError!Air.Inst.Ref {
15597 // TODO CLOSURE: Test this with inline functions
15706fn zirClosureGet(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15707 const mod = sema.mod;
1559815708 const inst_data = sema.code.instructions.items(.data)[inst].inst_node;
15599 var scope: *CaptureScope = sema.mod.declPtr(block.src_decl).src_scope.?;
15709 var scope: *CaptureScope = mod.declPtr(block.src_decl).src_scope.?;
1560015710 // Note: The target closure must be in this scope list.
1560115711 // If it's not here, the zir is invalid, or the list is broken.
15602 const tv = while (true) {
15712 const capture = while (true) {
1560315713 // Note: We don't need to add a dependency here, because
1560415714 // decls always depend on their lexical parents.
1560515715
......@@ -15612,17 +15722,17 @@ fn zirClosureGet(
1561215722 }
1561315723 return error.AnalysisFail;
1561415724 }
15615 if (scope.captures.getPtr(inst_data.inst)) |tv| {
15616 break tv;
15725 if (scope.captures.get(inst_data.inst)) |capture| {
15726 break capture;
1561715727 }
1561815728 scope = scope.parent.?;
1561915729 };
1562015730
15621 if (tv.val.tag() == .unreachable_value and !block.is_typeof and sema.func == null) {
15731 if (capture == .runtime_val and !block.is_typeof and sema.func_index == .none) {
1562215732 const msg = msg: {
1562315733 const name = name: {
15624 const file = sema.owner_decl.getFileScope();
15625 const tree = file.getTree(sema.mod.gpa) catch |err| {
15734 const file = sema.owner_decl.getFileScope(mod);
15735 const tree = file.getTree(sema.gpa) catch |err| {
1562615736 // In this case we emit a warning + a less precise source location.
1562715737 log.warn("unable to load {s}: {s}", .{
1562815738 file.sub_file_path, @errorName(err),
......@@ -15646,11 +15756,11 @@ fn zirClosureGet(
1564615756 return sema.failWithOwnedErrorMsg(msg);
1564715757 }
1564815758
15649 if (tv.val.tag() == .unreachable_value and !block.is_typeof and !block.is_comptime and sema.func != null) {
15759 if (capture == .runtime_val and !block.is_typeof and !block.is_comptime and sema.func_index != .none) {
1565015760 const msg = msg: {
1565115761 const name = name: {
15652 const file = sema.owner_decl.getFileScope();
15653 const tree = file.getTree(sema.mod.gpa) catch |err| {
15762 const file = sema.owner_decl.getFileScope(mod);
15763 const tree = file.getTree(sema.gpa) catch |err| {
1565415764 // In this case we emit a warning + a less precise source location.
1565515765 log.warn("unable to load {s}: {s}", .{
1565615766 file.sub_file_path, @errorName(err),
......@@ -15676,13 +15786,17 @@ fn zirClosureGet(
1567615786 return sema.failWithOwnedErrorMsg(msg);
1567715787 }
1567815788
15679 if (tv.val.tag() == .unreachable_value) {
15680 assert(block.is_typeof);
15681 // We need a dummy runtime instruction with the correct type.
15682 return block.addTy(.alloc, tv.ty);
15789 switch (capture) {
15790 .runtime_val => |ty_ip_index| {
15791 assert(block.is_typeof);
15792 // We need a dummy runtime instruction with the correct type.
15793 return block.addTy(.alloc, ty_ip_index.toType());
15794 },
15795 .comptime_val => |val_ip_index| {
15796 const ty = mod.intern_pool.typeOf(val_ip_index).toType();
15797 return sema.addConstant(ty, val_ip_index.toValue());
15798 },
1568315799 }
15684
15685 return sema.addConstant(tv.ty, tv.val);
1568615800}
1568715801
1568815802fn zirRetAddr(
......@@ -15717,345 +15831,422 @@ fn zirBuiltinSrc(
1571715831 const tracy = trace(@src());
1571815832 defer tracy.end();
1571915833
15834 const mod = sema.mod;
1572015835 const extra = sema.code.extraData(Zir.Inst.Src, extended.operand).data;
1572115836 const src = LazySrcLoc.nodeOffset(extra.node);
1572215837 const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});
15723 const fn_owner_decl = sema.mod.declPtr(func.owner_decl);
15838 const fn_owner_decl = mod.declPtr(func.owner_decl);
1572415839
1572515840 const func_name_val = blk: {
1572615841 var anon_decl = try block.startAnonDecl();
1572715842 defer anon_decl.deinit();
15728 const name = std.mem.span(fn_owner_decl.name);
15729 const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
15843 // TODO: write something like getCoercedInts to avoid needing to dupe
15844 const name = try sema.arena.dupe(u8, mod.intern_pool.stringToSlice(fn_owner_decl.name));
15845 const new_decl_ty = try mod.arrayType(.{
15846 .len = name.len,
15847 .child = .u8_type,
15848 .sentinel = .zero_u8,
15849 });
1573015850 const new_decl = try anon_decl.finish(
15731 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len - 1),
15732 try Value.Tag.bytes.create(anon_decl.arena(), bytes),
15851 new_decl_ty,
15852 (try mod.intern(.{ .aggregate = .{
15853 .ty = new_decl_ty.toIntern(),
15854 .storage = .{ .bytes = name },
15855 } })).toValue(),
1573315856 0, // default alignment
1573415857 );
15735 break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
15858 break :blk try mod.intern(.{ .ptr = .{
15859 .ty = .slice_const_u8_sentinel_0_type,
15860 .addr = .{ .decl = new_decl },
15861 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
15862 } });
1573615863 };
1573715864
1573815865 const file_name_val = blk: {
1573915866 var anon_decl = try block.startAnonDecl();
1574015867 defer anon_decl.deinit();
1574115868 // The compiler must not call realpath anywhere.
15742 const name = try fn_owner_decl.getFileScope().fullPathZ(anon_decl.arena());
15869 const name = try fn_owner_decl.getFileScope(mod).fullPathZ(sema.arena);
15870 const new_decl_ty = try mod.arrayType(.{
15871 .len = name.len,
15872 .child = .u8_type,
15873 .sentinel = .zero_u8,
15874 });
1574315875 const new_decl = try anon_decl.finish(
15744 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), name.len),
15745 try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
15876 new_decl_ty,
15877 (try mod.intern(.{ .aggregate = .{
15878 .ty = new_decl_ty.toIntern(),
15879 .storage = .{ .bytes = name },
15880 } })).toValue(),
1574615881 0, // default alignment
1574715882 );
15748 break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
15883 break :blk try mod.intern(.{ .ptr = .{
15884 .ty = .slice_const_u8_sentinel_0_type,
15885 .addr = .{ .decl = new_decl },
15886 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
15887 } });
1574915888 };
1575015889
15751 const field_values = try sema.arena.alloc(Value, 4);
15752 // file: [:0]const u8,
15753 field_values[0] = file_name_val;
15754 // fn_name: [:0]const u8,
15755 field_values[1] = func_name_val;
15756 // line: u32
15757 field_values[2] = try Value.Tag.runtime_value.create(sema.arena, try Value.Tag.int_u64.create(sema.arena, extra.line + 1));
15758 // column: u32,
15759 field_values[3] = try Value.Tag.int_u64.create(sema.arena, extra.column + 1);
15760
15761 return sema.addConstant(
15762 try sema.getBuiltinType("SourceLocation"),
15763 try Value.Tag.aggregate.create(sema.arena, field_values),
15764 );
15890 const src_loc_ty = try sema.getBuiltinType("SourceLocation");
15891 const fields = .{
15892 // file: [:0]const u8,
15893 file_name_val,
15894 // fn_name: [:0]const u8,
15895 func_name_val,
15896 // line: u32,
15897 try mod.intern(.{ .runtime_value = .{
15898 .ty = .u32_type,
15899 .val = (try mod.intValue(Type.u32, extra.line + 1)).toIntern(),
15900 } }),
15901 // column: u32,
15902 (try mod.intValue(Type.u32, extra.column + 1)).toIntern(),
15903 };
15904 return sema.addConstant(src_loc_ty, (try mod.intern(.{ .aggregate = .{
15905 .ty = src_loc_ty.toIntern(),
15906 .storage = .{ .elems = &fields },
15907 } })).toValue());
1576515908}
1576615909
1576715910fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
15911 const mod = sema.mod;
15912 const gpa = sema.gpa;
15913 const ip = &mod.intern_pool;
1576815914 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1576915915 const src = inst_data.src();
1577015916 const ty = try sema.resolveType(block, src, inst_data.operand);
1577115917 const type_info_ty = try sema.getBuiltinType("Type");
15772 const target = sema.mod.getTarget();
15918 const type_info_tag_ty = type_info_ty.unionTagType(mod).?;
1577315919
15774 switch (ty.zigTypeTag()) {
15775 .Type => return sema.addConstant(
15776 type_info_ty,
15777 try Value.Tag.@"union".create(sema.arena, .{
15778 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Type)),
15779 .val = Value.void,
15780 }),
15781 ),
15782 .Void => return sema.addConstant(
15783 type_info_ty,
15784 try Value.Tag.@"union".create(sema.arena, .{
15785 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Void)),
15786 .val = Value.void,
15787 }),
15788 ),
15789 .Bool => return sema.addConstant(
15790 type_info_ty,
15791 try Value.Tag.@"union".create(sema.arena, .{
15792 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Bool)),
15793 .val = Value.void,
15794 }),
15795 ),
15796 .NoReturn => return sema.addConstant(
15797 type_info_ty,
15798 try Value.Tag.@"union".create(sema.arena, .{
15799 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.NoReturn)),
15800 .val = Value.void,
15801 }),
15802 ),
15803 .ComptimeFloat => return sema.addConstant(
15804 type_info_ty,
15805 try Value.Tag.@"union".create(sema.arena, .{
15806 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeFloat)),
15807 .val = Value.void,
15808 }),
15809 ),
15810 .ComptimeInt => return sema.addConstant(
15811 type_info_ty,
15812 try Value.Tag.@"union".create(sema.arena, .{
15813 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ComptimeInt)),
15814 .val = Value.void,
15815 }),
15816 ),
15817 .Undefined => return sema.addConstant(
15818 type_info_ty,
15819 try Value.Tag.@"union".create(sema.arena, .{
15820 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Undefined)),
15821 .val = Value.void,
15822 }),
15823 ),
15824 .Null => return sema.addConstant(
15825 type_info_ty,
15826 try Value.Tag.@"union".create(sema.arena, .{
15827 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Null)),
15828 .val = Value.void,
15829 }),
15830 ),
15831 .EnumLiteral => return sema.addConstant(
15832 type_info_ty,
15833 try Value.Tag.@"union".create(sema.arena, .{
15834 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.EnumLiteral)),
15835 .val = Value.void,
15836 }),
15837 ),
15920 switch (ty.zigTypeTag(mod)) {
15921 .Type,
15922 .Void,
15923 .Bool,
15924 .NoReturn,
15925 .ComptimeFloat,
15926 .ComptimeInt,
15927 .Undefined,
15928 .Null,
15929 .EnumLiteral,
15930 => |type_info_tag| return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
15931 .ty = type_info_ty.toIntern(),
15932 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(type_info_tag))).toIntern(),
15933 .val = .void_value,
15934 } })).toValue()),
1583815935 .Fn => {
1583915936 // TODO: look into memoizing this result.
15840 const info = ty.fnInfo();
15841
1584215937 var params_anon_decl = try block.startAnonDecl();
1584315938 defer params_anon_decl.deinit();
1584415939
15845 const param_vals = try params_anon_decl.arena().alloc(Value, info.param_types.len);
15940 const fn_info_decl_index = (try sema.namespaceLookup(
15941 block,
15942 src,
15943 type_info_ty.getNamespaceIndex(mod).unwrap().?,
15944 try ip.getOrPutString(gpa, "Fn"),
15945 )).?;
15946 try mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index);
15947 try sema.ensureDeclAnalyzed(fn_info_decl_index);
15948 const fn_info_decl = mod.declPtr(fn_info_decl_index);
15949 const fn_info_ty = fn_info_decl.val.toType();
15950
15951 const param_info_decl_index = (try sema.namespaceLookup(
15952 block,
15953 src,
15954 fn_info_ty.getNamespaceIndex(mod).unwrap().?,
15955 try ip.getOrPutString(gpa, "Param"),
15956 )).?;
15957 try mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index);
15958 try sema.ensureDeclAnalyzed(param_info_decl_index);
15959 const param_info_decl = mod.declPtr(param_info_decl_index);
15960 const param_info_ty = param_info_decl.val.toType();
15961
15962 const param_vals = try sema.arena.alloc(InternPool.Index, mod.typeToFunc(ty).?.param_types.len);
1584615963 for (param_vals, 0..) |*param_val, i| {
15964 const info = mod.typeToFunc(ty).?;
1584715965 const param_ty = info.param_types[i];
15848 const is_generic = param_ty.tag() == .generic_poison;
15849 const param_ty_val = if (is_generic)
15850 Value.null
15851 else
15852 try Value.Tag.opt_payload.create(
15853 params_anon_decl.arena(),
15854 try Value.Tag.ty.create(params_anon_decl.arena(), try param_ty.copy(params_anon_decl.arena())),
15855 );
15966 const is_generic = param_ty == .generic_poison_type;
15967 const param_ty_val = try ip.get(gpa, .{ .opt = .{
15968 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
15969 .val = if (is_generic) .none else param_ty,
15970 } });
1585615971
1585715972 const is_noalias = blk: {
1585815973 const index = std.math.cast(u5, i) orelse break :blk false;
1585915974 break :blk @truncate(u1, info.noalias_bits >> index) != 0;
1586015975 };
1586115976
15862 const param_fields = try params_anon_decl.arena().create([3]Value);
15863 param_fields.* = .{
15977 const param_fields = .{
1586415978 // is_generic: bool,
15865 Value.makeBool(is_generic),
15979 Value.makeBool(is_generic).toIntern(),
1586615980 // is_noalias: bool,
15867 Value.makeBool(is_noalias),
15981 Value.makeBool(is_noalias).toIntern(),
1586815982 // type: ?type,
1586915983 param_ty_val,
1587015984 };
15871 param_val.* = try Value.Tag.aggregate.create(params_anon_decl.arena(), param_fields);
15985 param_val.* = try mod.intern(.{ .aggregate = .{
15986 .ty = param_info_ty.toIntern(),
15987 .storage = .{ .elems = &param_fields },
15988 } });
1587215989 }
1587315990
1587415991 const args_val = v: {
15875 const fn_info_decl_index = (try sema.namespaceLookup(
15876 block,
15877 src,
15878 type_info_ty.getNamespace().?,
15879 "Fn",
15880 )).?;
15881 try sema.mod.declareDeclDependency(sema.owner_decl_index, fn_info_decl_index);
15882 try sema.ensureDeclAnalyzed(fn_info_decl_index);
15883 const fn_info_decl = sema.mod.declPtr(fn_info_decl_index);
15884 var fn_ty_buffer: Value.ToTypeBuffer = undefined;
15885 const fn_ty = fn_info_decl.val.toType(&fn_ty_buffer);
15886 const param_info_decl_index = (try sema.namespaceLookup(
15887 block,
15888 src,
15889 fn_ty.getNamespace().?,
15890 "Param",
15891 )).?;
15892 try sema.mod.declareDeclDependency(sema.owner_decl_index, param_info_decl_index);
15893 try sema.ensureDeclAnalyzed(param_info_decl_index);
15894 const param_info_decl = sema.mod.declPtr(param_info_decl_index);
15895 var param_buffer: Value.ToTypeBuffer = undefined;
15896 const param_ty = param_info_decl.val.toType(&param_buffer);
15992 const new_decl_ty = try mod.arrayType(.{
15993 .len = param_vals.len,
15994 .child = param_info_ty.toIntern(),
15995 });
1589715996 const new_decl = try params_anon_decl.finish(
15898 try Type.Tag.array.create(params_anon_decl.arena(), .{
15899 .len = param_vals.len,
15900 .elem_type = try param_ty.copy(params_anon_decl.arena()),
15901 }),
15902 try Value.Tag.aggregate.create(
15903 params_anon_decl.arena(),
15904 param_vals,
15905 ),
15997 new_decl_ty,
15998 (try mod.intern(.{ .aggregate = .{
15999 .ty = new_decl_ty.toIntern(),
16000 .storage = .{ .elems = param_vals },
16001 } })).toValue(),
1590616002 0, // default alignment
1590716003 );
15908 break :v try Value.Tag.slice.create(sema.arena, .{
15909 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
15910 .len = try Value.Tag.int_u64.create(sema.arena, param_vals.len),
15911 });
16004 break :v try mod.intern(.{ .ptr = .{
16005 .ty = (try mod.ptrType(.{
16006 .child = param_info_ty.toIntern(),
16007 .flags = .{
16008 .size = .Slice,
16009 .is_const = true,
16010 },
16011 })).toIntern(),
16012 .addr = .{ .decl = new_decl },
16013 .len = (try mod.intValue(Type.usize, param_vals.len)).toIntern(),
16014 } });
1591216015 };
1591316016
15914 const ret_ty_opt = if (info.return_type.tag() != .generic_poison)
15915 try Value.Tag.opt_payload.create(
15916 sema.arena,
15917 try Value.Tag.ty.create(sema.arena, info.return_type),
15918 )
15919 else
15920 Value.null;
16017 const info = mod.typeToFunc(ty).?;
16018 const ret_ty_opt = try mod.intern(.{ .opt = .{
16019 .ty = try ip.get(gpa, .{ .opt_type = .type_type }),
16020 .val = if (info.return_type == .generic_poison_type) .none else info.return_type,
16021 } });
16022
16023 const callconv_ty = try sema.getBuiltinType("CallingConvention");
1592116024
15922 const field_values = try sema.arena.create([6]Value);
15923 field_values.* = .{
16025 const field_values = .{
1592416026 // calling_convention: CallingConvention,
15925 try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.cc)),
16027 (try mod.enumValueFieldIndex(callconv_ty, @enumToInt(info.cc))).toIntern(),
1592616028 // alignment: comptime_int,
15927 try Value.Tag.int_u64.create(sema.arena, ty.abiAlignment(target)),
16029 (try mod.intValue(Type.comptime_int, ty.abiAlignment(mod))).toIntern(),
1592816030 // is_generic: bool,
15929 Value.makeBool(info.is_generic),
16031 Value.makeBool(info.is_generic).toIntern(),
1593016032 // is_var_args: bool,
15931 Value.makeBool(info.is_var_args),
16033 Value.makeBool(info.is_var_args).toIntern(),
1593216034 // return_type: ?type,
1593316035 ret_ty_opt,
1593416036 // args: []const Fn.Param,
1593516037 args_val,
1593616038 };
15937
15938 return sema.addConstant(
15939 type_info_ty,
15940 try Value.Tag.@"union".create(sema.arena, .{
15941 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Fn)),
15942 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
15943 }),
15944 );
16039 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16040 .ty = type_info_ty.toIntern(),
16041 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Fn))).toIntern(),
16042 .val = try mod.intern(.{ .aggregate = .{
16043 .ty = fn_info_ty.toIntern(),
16044 .storage = .{ .elems = &field_values },
16045 } }),
16046 } })).toValue());
1594516047 },
1594616048 .Int => {
15947 const info = ty.intInfo(target);
15948 const field_values = try sema.arena.alloc(Value, 2);
15949 // signedness: Signedness,
15950 field_values[0] = try Value.Tag.enum_field_index.create(
15951 sema.arena,
15952 @enumToInt(info.signedness),
15953 );
15954 // bits: comptime_int,
15955 field_values[1] = try Value.Tag.int_u64.create(sema.arena, info.bits);
15956
15957 return sema.addConstant(
15958 type_info_ty,
15959 try Value.Tag.@"union".create(sema.arena, .{
15960 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Int)),
15961 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
15962 }),
15963 );
16049 const int_info_decl_index = (try sema.namespaceLookup(
16050 block,
16051 src,
16052 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16053 try ip.getOrPutString(gpa, "Int"),
16054 )).?;
16055 try mod.declareDeclDependency(sema.owner_decl_index, int_info_decl_index);
16056 try sema.ensureDeclAnalyzed(int_info_decl_index);
16057 const int_info_decl = mod.declPtr(int_info_decl_index);
16058 const int_info_ty = int_info_decl.val.toType();
16059
16060 const signedness_ty = try sema.getBuiltinType("Signedness");
16061 const info = ty.intInfo(mod);
16062 const field_values = .{
16063 // signedness: Signedness,
16064 try (try mod.enumValueFieldIndex(signedness_ty, @enumToInt(info.signedness))).intern(signedness_ty, mod),
16065 // bits: u16,
16066 (try mod.intValue(Type.u16, info.bits)).toIntern(),
16067 };
16068 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16069 .ty = type_info_ty.toIntern(),
16070 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Int))).toIntern(),
16071 .val = try mod.intern(.{ .aggregate = .{
16072 .ty = int_info_ty.toIntern(),
16073 .storage = .{ .elems = &field_values },
16074 } }),
16075 } })).toValue());
1596416076 },
1596516077 .Float => {
15966 const field_values = try sema.arena.alloc(Value, 1);
15967 // bits: comptime_int,
15968 field_values[0] = try Value.Tag.int_u64.create(sema.arena, ty.bitSize(target));
15969
15970 return sema.addConstant(
15971 type_info_ty,
15972 try Value.Tag.@"union".create(sema.arena, .{
15973 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Float)),
15974 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
15975 }),
15976 );
16078 const float_info_decl_index = (try sema.namespaceLookup(
16079 block,
16080 src,
16081 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16082 try ip.getOrPutString(gpa, "Float"),
16083 )).?;
16084 try mod.declareDeclDependency(sema.owner_decl_index, float_info_decl_index);
16085 try sema.ensureDeclAnalyzed(float_info_decl_index);
16086 const float_info_decl = mod.declPtr(float_info_decl_index);
16087 const float_info_ty = float_info_decl.val.toType();
16088
16089 const field_vals = .{
16090 // bits: u16,
16091 (try mod.intValue(Type.u16, ty.bitSize(mod))).toIntern(),
16092 };
16093 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16094 .ty = type_info_ty.toIntern(),
16095 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Float))).toIntern(),
16096 .val = try mod.intern(.{ .aggregate = .{
16097 .ty = float_info_ty.toIntern(),
16098 .storage = .{ .elems = &field_vals },
16099 } }),
16100 } })).toValue());
1597716101 },
1597816102 .Pointer => {
15979 const info = ty.ptrInfo().data;
16103 const info = ty.ptrInfo(mod);
1598016104 const alignment = if (info.@"align" != 0)
15981 try Value.Tag.int_u64.create(sema.arena, info.@"align")
16105 try mod.intValue(Type.comptime_int, info.@"align")
1598216106 else
15983 try info.pointee_type.lazyAbiAlignment(target, sema.arena);
16107 try info.pointee_type.lazyAbiAlignment(mod);
1598416108
15985 const field_values = try sema.arena.create([8]Value);
15986 field_values.* = .{
16109 const addrspace_ty = try sema.getBuiltinType("AddressSpace");
16110 const pointer_ty = t: {
16111 const decl_index = (try sema.namespaceLookup(
16112 block,
16113 src,
16114 (try sema.getBuiltinType("Type")).getNamespaceIndex(mod).unwrap().?,
16115 try ip.getOrPutString(gpa, "Pointer"),
16116 )).?;
16117 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
16118 try sema.ensureDeclAnalyzed(decl_index);
16119 const decl = mod.declPtr(decl_index);
16120 break :t decl.val.toType();
16121 };
16122 const ptr_size_ty = t: {
16123 const decl_index = (try sema.namespaceLookup(
16124 block,
16125 src,
16126 pointer_ty.getNamespaceIndex(mod).unwrap().?,
16127 try ip.getOrPutString(gpa, "Size"),
16128 )).?;
16129 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
16130 try sema.ensureDeclAnalyzed(decl_index);
16131 const decl = mod.declPtr(decl_index);
16132 break :t decl.val.toType();
16133 };
16134
16135 const field_values = .{
1598716136 // size: Size,
15988 try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.size)),
16137 try (try mod.enumValueFieldIndex(ptr_size_ty, @enumToInt(info.size))).intern(ptr_size_ty, mod),
1598916138 // is_const: bool,
15990 Value.makeBool(!info.mutable),
16139 Value.makeBool(!info.mutable).toIntern(),
1599116140 // is_volatile: bool,
15992 Value.makeBool(info.@"volatile"),
16141 Value.makeBool(info.@"volatile").toIntern(),
1599316142 // alignment: comptime_int,
15994 alignment,
16143 alignment.toIntern(),
1599516144 // address_space: AddressSpace
15996 try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(info.@"addrspace")),
16145 try (try mod.enumValueFieldIndex(addrspace_ty, @enumToInt(info.@"addrspace"))).intern(addrspace_ty, mod),
1599716146 // child: type,
15998 try Value.Tag.ty.create(sema.arena, info.pointee_type),
16147 info.pointee_type.toIntern(),
1599916148 // is_allowzero: bool,
16000 Value.makeBool(info.@"allowzero"),
16149 Value.makeBool(info.@"allowzero").toIntern(),
1600116150 // sentinel: ?*const anyopaque,
16002 try sema.optRefValue(block, info.pointee_type, info.sentinel),
16151 (try sema.optRefValue(block, info.pointee_type, info.sentinel)).toIntern(),
1600316152 };
16004
16005 return sema.addConstant(
16006 type_info_ty,
16007 try Value.Tag.@"union".create(sema.arena, .{
16008 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Pointer)),
16009 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16010 }),
16011 );
16153 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16154 .ty = type_info_ty.toIntern(),
16155 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Pointer))).toIntern(),
16156 .val = try mod.intern(.{ .aggregate = .{
16157 .ty = pointer_ty.toIntern(),
16158 .storage = .{ .elems = &field_values },
16159 } }),
16160 } })).toValue());
1601216161 },
1601316162 .Array => {
16014 const info = ty.arrayInfo();
16015 const field_values = try sema.arena.alloc(Value, 3);
16016 // len: comptime_int,
16017 field_values[0] = try Value.Tag.int_u64.create(sema.arena, info.len);
16018 // child: type,
16019 field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);
16020 // sentinel: ?*const anyopaque,
16021 field_values[2] = try sema.optRefValue(block, info.elem_type, info.sentinel);
16022
16023 return sema.addConstant(
16024 type_info_ty,
16025 try Value.Tag.@"union".create(sema.arena, .{
16026 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Array)),
16027 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16028 }),
16029 );
16163 const array_field_ty = t: {
16164 const array_field_ty_decl_index = (try sema.namespaceLookup(
16165 block,
16166 src,
16167 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16168 try ip.getOrPutString(gpa, "Array"),
16169 )).?;
16170 try mod.declareDeclDependency(sema.owner_decl_index, array_field_ty_decl_index);
16171 try sema.ensureDeclAnalyzed(array_field_ty_decl_index);
16172 const array_field_ty_decl = mod.declPtr(array_field_ty_decl_index);
16173 break :t array_field_ty_decl.val.toType();
16174 };
16175
16176 const info = ty.arrayInfo(mod);
16177 const field_values = .{
16178 // len: comptime_int,
16179 (try mod.intValue(Type.comptime_int, info.len)).toIntern(),
16180 // child: type,
16181 info.elem_type.toIntern(),
16182 // sentinel: ?*const anyopaque,
16183 (try sema.optRefValue(block, info.elem_type, info.sentinel)).toIntern(),
16184 };
16185 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16186 .ty = type_info_ty.toIntern(),
16187 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Array))).toIntern(),
16188 .val = try mod.intern(.{ .aggregate = .{
16189 .ty = array_field_ty.toIntern(),
16190 .storage = .{ .elems = &field_values },
16191 } }),
16192 } })).toValue());
1603016193 },
1603116194 .Vector => {
16032 const info = ty.arrayInfo();
16033 const field_values = try sema.arena.alloc(Value, 2);
16034 // len: comptime_int,
16035 field_values[0] = try Value.Tag.int_u64.create(sema.arena, info.len);
16036 // child: type,
16037 field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);
16038
16039 return sema.addConstant(
16040 type_info_ty,
16041 try Value.Tag.@"union".create(sema.arena, .{
16042 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Vector)),
16043 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16044 }),
16045 );
16195 const vector_field_ty = t: {
16196 const vector_field_ty_decl_index = (try sema.namespaceLookup(
16197 block,
16198 src,
16199 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16200 try ip.getOrPutString(gpa, "Vector"),
16201 )).?;
16202 try mod.declareDeclDependency(sema.owner_decl_index, vector_field_ty_decl_index);
16203 try sema.ensureDeclAnalyzed(vector_field_ty_decl_index);
16204 const vector_field_ty_decl = mod.declPtr(vector_field_ty_decl_index);
16205 break :t vector_field_ty_decl.val.toType();
16206 };
16207
16208 const info = ty.arrayInfo(mod);
16209 const field_values = .{
16210 // len: comptime_int,
16211 (try mod.intValue(Type.comptime_int, info.len)).toIntern(),
16212 // child: type,
16213 info.elem_type.toIntern(),
16214 };
16215 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16216 .ty = type_info_ty.toIntern(),
16217 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Vector))).toIntern(),
16218 .val = try mod.intern(.{ .aggregate = .{
16219 .ty = vector_field_ty.toIntern(),
16220 .storage = .{ .elems = &field_values },
16221 } }),
16222 } })).toValue());
1604616223 },
1604716224 .Optional => {
16048 const field_values = try sema.arena.alloc(Value, 1);
16049 // child: type,
16050 field_values[0] = try Value.Tag.ty.create(sema.arena, try ty.optionalChildAlloc(sema.arena));
16051
16052 return sema.addConstant(
16053 type_info_ty,
16054 try Value.Tag.@"union".create(sema.arena, .{
16055 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Optional)),
16056 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16057 }),
16058 );
16225 const optional_field_ty = t: {
16226 const optional_field_ty_decl_index = (try sema.namespaceLookup(
16227 block,
16228 src,
16229 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16230 try ip.getOrPutString(gpa, "Optional"),
16231 )).?;
16232 try mod.declareDeclDependency(sema.owner_decl_index, optional_field_ty_decl_index);
16233 try sema.ensureDeclAnalyzed(optional_field_ty_decl_index);
16234 const optional_field_ty_decl = mod.declPtr(optional_field_ty_decl_index);
16235 break :t optional_field_ty_decl.val.toType();
16236 };
16237
16238 const field_values = .{
16239 // child: type,
16240 ty.optionalChild(mod).toIntern(),
16241 };
16242 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16243 .ty = type_info_ty.toIntern(),
16244 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Optional))).toIntern(),
16245 .val = try mod.intern(.{ .aggregate = .{
16246 .ty = optional_field_ty.toIntern(),
16247 .storage = .{ .elems = &field_values },
16248 } }),
16249 } })).toValue());
1605916250 },
1606016251 .ErrorSet => {
1606116252 var fields_anon_decl = try block.startAnonDecl();
......@@ -16066,17 +16257,16 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1606616257 const set_field_ty_decl_index = (try sema.namespaceLookup(
1606716258 block,
1606816259 src,
16069 type_info_ty.getNamespace().?,
16070 "Error",
16260 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16261 try ip.getOrPutString(gpa, "Error"),
1607116262 )).?;
16072 try sema.mod.declareDeclDependency(sema.owner_decl_index, set_field_ty_decl_index);
16263 try mod.declareDeclDependency(sema.owner_decl_index, set_field_ty_decl_index);
1607316264 try sema.ensureDeclAnalyzed(set_field_ty_decl_index);
16074 const set_field_ty_decl = sema.mod.declPtr(set_field_ty_decl_index);
16075 var buffer: Value.ToTypeBuffer = undefined;
16076 break :t try set_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16265 const set_field_ty_decl = mod.declPtr(set_field_ty_decl_index);
16266 break :t set_field_ty_decl.val.toType();
1607716267 };
1607816268
16079 try sema.queueFullTypeResolution(try error_field_ty.copy(sema.arena));
16269 try sema.queueFullTypeResolution(error_field_ty);
1608016270
1608116271 // If the error set is inferred it must be resolved at this point
1608216272 try sema.resolveInferredErrorSetTy(block, src, ty);
......@@ -16084,90 +16274,119 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1608416274 // Build our list of Error values
1608516275 // Optional value is only null if anyerror
1608616276 // Value can be zero-length slice otherwise
16087 const error_field_vals: ?[]Value = if (ty.isAnyError()) null else blk: {
16088 const names = ty.errorSetNames();
16089 const vals = try fields_anon_decl.arena().alloc(Value, names.len);
16277 const error_field_vals = if (ty.isAnyError(mod)) null else blk: {
16278 const vals = try sema.arena.alloc(InternPool.Index, ty.errorSetNames(mod).len);
1609016279 for (vals, 0..) |*field_val, i| {
16091 const name = names[i];
16280 // TODO: write something like getCoercedInts to avoid needing to dupe
16281 const name = try sema.arena.dupe(u8, ip.stringToSlice(ty.errorSetNames(mod)[i]));
1609216282 const name_val = v: {
1609316283 var anon_decl = try block.startAnonDecl();
1609416284 defer anon_decl.deinit();
16095 const bytes = try anon_decl.arena().dupeZ(u8, name);
16285 const new_decl_ty = try mod.arrayType(.{
16286 .len = name.len,
16287 .child = .u8_type,
16288 });
1609616289 const new_decl = try anon_decl.finish(
16097 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
16098 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16290 new_decl_ty,
16291 (try mod.intern(.{ .aggregate = .{
16292 .ty = new_decl_ty.toIntern(),
16293 .storage = .{ .bytes = name },
16294 } })).toValue(),
1609916295 0, // default alignment
1610016296 );
16101 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
16297 break :v try mod.intern(.{ .ptr = .{
16298 .ty = .slice_const_u8_type,
16299 .addr = .{ .decl = new_decl },
16300 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16301 } });
1610216302 };
1610316303
16104 const error_field_fields = try fields_anon_decl.arena().create([1]Value);
16105 error_field_fields.* = .{
16304 const error_field_fields = .{
1610616305 // name: []const u8,
1610716306 name_val,
1610816307 };
16109
16110 field_val.* = try Value.Tag.aggregate.create(
16111 fields_anon_decl.arena(),
16112 error_field_fields,
16113 );
16308 field_val.* = try mod.intern(.{ .aggregate = .{
16309 .ty = error_field_ty.toIntern(),
16310 .storage = .{ .elems = &error_field_fields },
16311 } });
1611416312 }
1611516313
1611616314 break :blk vals;
1611716315 };
1611816316
1611916317 // Build our ?[]const Error value
16120 const errors_val = if (error_field_vals) |vals| v: {
16318 const slice_errors_ty = try mod.ptrType(.{
16319 .child = error_field_ty.toIntern(),
16320 .flags = .{
16321 .size = .Slice,
16322 .is_const = true,
16323 },
16324 });
16325 const opt_slice_errors_ty = try mod.optionalType(slice_errors_ty.toIntern());
16326 const errors_payload_val: InternPool.Index = if (error_field_vals) |vals| v: {
16327 const array_errors_ty = try mod.arrayType(.{
16328 .len = vals.len,
16329 .child = error_field_ty.toIntern(),
16330 .sentinel = .none,
16331 });
1612116332 const new_decl = try fields_anon_decl.finish(
16122 try Type.Tag.array.create(fields_anon_decl.arena(), .{
16123 .len = vals.len,
16124 .elem_type = error_field_ty,
16125 }),
16126 try Value.Tag.aggregate.create(
16127 fields_anon_decl.arena(),
16128 vals,
16129 ),
16333 array_errors_ty,
16334 (try mod.intern(.{ .aggregate = .{
16335 .ty = array_errors_ty.toIntern(),
16336 .storage = .{ .elems = vals },
16337 } })).toValue(),
1613016338 0, // default alignment
1613116339 );
16132
16133 const new_decl_val = try Value.Tag.decl_ref.create(sema.arena, new_decl);
16134 const slice_val = try Value.Tag.slice.create(sema.arena, .{
16135 .ptr = new_decl_val,
16136 .len = try Value.Tag.int_u64.create(sema.arena, vals.len),
16137 });
16138 break :v try Value.Tag.opt_payload.create(sema.arena, slice_val);
16139 } else Value.null;
16340 break :v try mod.intern(.{ .ptr = .{
16341 .ty = slice_errors_ty.toIntern(),
16342 .addr = .{ .decl = new_decl },
16343 .len = (try mod.intValue(Type.usize, vals.len)).toIntern(),
16344 } });
16345 } else .none;
16346 const errors_val = try mod.intern(.{ .opt = .{
16347 .ty = opt_slice_errors_ty.toIntern(),
16348 .val = errors_payload_val,
16349 } });
1614016350
1614116351 // Construct Type{ .ErrorSet = errors_val }
16142 return sema.addConstant(
16143 type_info_ty,
16144 try Value.Tag.@"union".create(sema.arena, .{
16145 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ErrorSet)),
16146 .val = errors_val,
16147 }),
16148 );
16352 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16353 .ty = type_info_ty.toIntern(),
16354 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorSet))).toIntern(),
16355 .val = errors_val,
16356 } })).toValue());
1614916357 },
1615016358 .ErrorUnion => {
16151 const field_values = try sema.arena.alloc(Value, 2);
16152 // error_set: type,
16153 field_values[0] = try Value.Tag.ty.create(sema.arena, ty.errorUnionSet());
16154 // payload: type,
16155 field_values[1] = try Value.Tag.ty.create(sema.arena, ty.errorUnionPayload());
16156
16157 return sema.addConstant(
16158 type_info_ty,
16159 try Value.Tag.@"union".create(sema.arena, .{
16160 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.ErrorUnion)),
16161 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16162 }),
16163 );
16359 const error_union_field_ty = t: {
16360 const error_union_field_ty_decl_index = (try sema.namespaceLookup(
16361 block,
16362 src,
16363 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16364 try ip.getOrPutString(gpa, "ErrorUnion"),
16365 )).?;
16366 try mod.declareDeclDependency(sema.owner_decl_index, error_union_field_ty_decl_index);
16367 try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index);
16368 const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index);
16369 break :t error_union_field_ty_decl.val.toType();
16370 };
16371
16372 const field_values = .{
16373 // error_set: type,
16374 ty.errorUnionSet(mod).toIntern(),
16375 // payload: type,
16376 ty.errorUnionPayload(mod).toIntern(),
16377 };
16378 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16379 .ty = type_info_ty.toIntern(),
16380 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.ErrorUnion))).toIntern(),
16381 .val = try mod.intern(.{ .aggregate = .{
16382 .ty = error_union_field_ty.toIntern(),
16383 .storage = .{ .elems = &field_values },
16384 } }),
16385 } })).toValue());
1616416386 },
1616516387 .Enum => {
1616616388 // TODO: look into memoizing this result.
16167 var int_tag_type_buffer: Type.Payload.Bits = undefined;
16168 const int_tag_ty = try ty.intTagType(&int_tag_type_buffer).copy(sema.arena);
16169
16170 const is_exhaustive = Value.makeBool(!ty.isNonexhaustiveEnum());
16389 const is_exhaustive = Value.makeBool(ip.indexToKey(ty.toIntern()).enum_type.tag_mode != .nonexhaustive);
1617116390
1617216391 var fields_anon_decl = try block.startAnonDecl();
1617316392 defer fields_anon_decl.deinit();
......@@ -16176,88 +16395,121 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1617616395 const enum_field_ty_decl_index = (try sema.namespaceLookup(
1617716396 block,
1617816397 src,
16179 type_info_ty.getNamespace().?,
16180 "EnumField",
16398 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16399 try ip.getOrPutString(gpa, "EnumField"),
1618116400 )).?;
16182 try sema.mod.declareDeclDependency(sema.owner_decl_index, enum_field_ty_decl_index);
16401 try mod.declareDeclDependency(sema.owner_decl_index, enum_field_ty_decl_index);
1618316402 try sema.ensureDeclAnalyzed(enum_field_ty_decl_index);
16184 const enum_field_ty_decl = sema.mod.declPtr(enum_field_ty_decl_index);
16185 var buffer: Value.ToTypeBuffer = undefined;
16186 break :t try enum_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16403 const enum_field_ty_decl = mod.declPtr(enum_field_ty_decl_index);
16404 break :t enum_field_ty_decl.val.toType();
1618716405 };
1618816406
16189 const enum_fields = ty.enumFields();
16190 const enum_field_vals = try fields_anon_decl.arena().alloc(Value, enum_fields.count());
16191
16407 const enum_field_vals = try sema.arena.alloc(InternPool.Index, ip.indexToKey(ty.toIntern()).enum_type.names.len);
1619216408 for (enum_field_vals, 0..) |*field_val, i| {
16193 var tag_val_payload: Value.Payload.U32 = .{
16194 .base = .{ .tag = .enum_field_index },
16195 .data = @intCast(u32, i),
16196 };
16197 const tag_val = Value.initPayload(&tag_val_payload.base);
16198
16199 var buffer: Value.Payload.U64 = undefined;
16200 const int_val = try tag_val.enumToInt(ty, &buffer).copy(fields_anon_decl.arena());
16201
16202 const name = enum_fields.keys()[i];
16409 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
16410 const value_val = if (enum_type.values.len > 0)
16411 try mod.intern_pool.getCoerced(gpa, enum_type.values[i], .comptime_int_type)
16412 else
16413 try mod.intern(.{ .int = .{
16414 .ty = .comptime_int_type,
16415 .storage = .{ .u64 = @intCast(u64, i) },
16416 } });
16417 // TODO: write something like getCoercedInts to avoid needing to dupe
16418 const name = try sema.arena.dupe(u8, ip.stringToSlice(enum_type.names[i]));
1620316419 const name_val = v: {
1620416420 var anon_decl = try block.startAnonDecl();
1620516421 defer anon_decl.deinit();
16206 const bytes = try anon_decl.arena().dupeZ(u8, name);
16422 const new_decl_ty = try mod.arrayType(.{
16423 .len = name.len,
16424 .child = .u8_type,
16425 });
1620716426 const new_decl = try anon_decl.finish(
16208 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
16209 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16427 new_decl_ty,
16428 (try mod.intern(.{ .aggregate = .{
16429 .ty = new_decl_ty.toIntern(),
16430 .storage = .{ .bytes = name },
16431 } })).toValue(),
1621016432 0, // default alignment
1621116433 );
16212 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
16434 break :v try mod.intern(.{ .ptr = .{
16435 .ty = .slice_const_u8_type,
16436 .addr = .{ .decl = new_decl },
16437 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16438 } });
1621316439 };
1621416440
16215 const enum_field_fields = try fields_anon_decl.arena().create([2]Value);
16216 enum_field_fields.* = .{
16441 const enum_field_fields = .{
1621716442 // name: []const u8,
1621816443 name_val,
1621916444 // value: comptime_int,
16220 int_val,
16445 value_val,
1622116446 };
16222 field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), enum_field_fields);
16447 field_val.* = try mod.intern(.{ .aggregate = .{
16448 .ty = enum_field_ty.toIntern(),
16449 .storage = .{ .elems = &enum_field_fields },
16450 } });
1622316451 }
1622416452
1622516453 const fields_val = v: {
16454 const fields_array_ty = try mod.arrayType(.{
16455 .len = enum_field_vals.len,
16456 .child = enum_field_ty.toIntern(),
16457 .sentinel = .none,
16458 });
1622616459 const new_decl = try fields_anon_decl.finish(
16227 try Type.Tag.array.create(fields_anon_decl.arena(), .{
16228 .len = enum_field_vals.len,
16229 .elem_type = enum_field_ty,
16230 }),
16231 try Value.Tag.aggregate.create(
16232 fields_anon_decl.arena(),
16233 enum_field_vals,
16234 ),
16460 fields_array_ty,
16461 (try mod.intern(.{ .aggregate = .{
16462 .ty = fields_array_ty.toIntern(),
16463 .storage = .{ .elems = enum_field_vals },
16464 } })).toValue(),
1623516465 0, // default alignment
1623616466 );
16237 break :v try Value.Tag.decl_ref.create(sema.arena, new_decl);
16467 break :v try mod.intern(.{ .ptr = .{
16468 .ty = (try mod.ptrType(.{
16469 .child = enum_field_ty.toIntern(),
16470 .flags = .{
16471 .size = .Slice,
16472 .is_const = true,
16473 },
16474 })).toIntern(),
16475 .addr = .{ .decl = new_decl },
16476 .len = (try mod.intValue(Type.usize, enum_field_vals.len)).toIntern(),
16477 } });
1623816478 };
1623916479
16240 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ty.getNamespace());
16480 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, ip.indexToKey(ty.toIntern()).enum_type.namespace);
16481
16482 const type_enum_ty = t: {
16483 const type_enum_ty_decl_index = (try sema.namespaceLookup(
16484 block,
16485 src,
16486 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16487 try ip.getOrPutString(gpa, "Enum"),
16488 )).?;
16489 try mod.declareDeclDependency(sema.owner_decl_index, type_enum_ty_decl_index);
16490 try sema.ensureDeclAnalyzed(type_enum_ty_decl_index);
16491 const type_enum_ty_decl = mod.declPtr(type_enum_ty_decl_index);
16492 break :t type_enum_ty_decl.val.toType();
16493 };
1624116494
16242 const field_values = try sema.arena.create([4]Value);
16243 field_values.* = .{
16495 const field_values = .{
1624416496 // tag_type: type,
16245 try Value.Tag.ty.create(sema.arena, int_tag_ty),
16497 ip.indexToKey(ty.toIntern()).enum_type.tag_ty,
1624616498 // fields: []const EnumField,
1624716499 fields_val,
1624816500 // decls: []const Declaration,
1624916501 decls_val,
1625016502 // is_exhaustive: bool,
16251 is_exhaustive,
16503 is_exhaustive.toIntern(),
1625216504 };
16253
16254 return sema.addConstant(
16255 type_info_ty,
16256 try Value.Tag.@"union".create(sema.arena, .{
16257 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Enum)),
16258 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16259 }),
16260 );
16505 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16506 .ty = type_info_ty.toIntern(),
16507 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Enum))).toIntern(),
16508 .val = try mod.intern(.{ .aggregate = .{
16509 .ty = type_enum_ty.toIntern(),
16510 .storage = .{ .elems = &field_values },
16511 } }),
16512 } })).toValue());
1626116513 },
1626216514 .Union => {
1626316515 // TODO: look into memoizing this result.
......@@ -16265,91 +16517,135 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1626516517 var fields_anon_decl = try block.startAnonDecl();
1626616518 defer fields_anon_decl.deinit();
1626716519
16520 const type_union_ty = t: {
16521 const type_union_ty_decl_index = (try sema.namespaceLookup(
16522 block,
16523 src,
16524 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16525 try ip.getOrPutString(gpa, "Union"),
16526 )).?;
16527 try mod.declareDeclDependency(sema.owner_decl_index, type_union_ty_decl_index);
16528 try sema.ensureDeclAnalyzed(type_union_ty_decl_index);
16529 const type_union_ty_decl = mod.declPtr(type_union_ty_decl_index);
16530 break :t type_union_ty_decl.val.toType();
16531 };
16532
1626816533 const union_field_ty = t: {
1626916534 const union_field_ty_decl_index = (try sema.namespaceLookup(
1627016535 block,
1627116536 src,
16272 type_info_ty.getNamespace().?,
16273 "UnionField",
16537 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16538 try ip.getOrPutString(gpa, "UnionField"),
1627416539 )).?;
16275 try sema.mod.declareDeclDependency(sema.owner_decl_index, union_field_ty_decl_index);
16540 try mod.declareDeclDependency(sema.owner_decl_index, union_field_ty_decl_index);
1627616541 try sema.ensureDeclAnalyzed(union_field_ty_decl_index);
16277 const union_field_ty_decl = sema.mod.declPtr(union_field_ty_decl_index);
16278 var buffer: Value.ToTypeBuffer = undefined;
16279 break :t try union_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16542 const union_field_ty_decl = mod.declPtr(union_field_ty_decl_index);
16543 break :t union_field_ty_decl.val.toType();
1628016544 };
1628116545
1628216546 const union_ty = try sema.resolveTypeFields(ty);
1628316547 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16284 const layout = union_ty.containerLayout();
16548 const layout = union_ty.containerLayout(mod);
1628516549
16286 const union_fields = union_ty.unionFields();
16287 const union_field_vals = try fields_anon_decl.arena().alloc(Value, union_fields.count());
16550 const union_fields = union_ty.unionFields(mod);
16551 const union_field_vals = try gpa.alloc(InternPool.Index, union_fields.count());
16552 defer gpa.free(union_field_vals);
1628816553
1628916554 for (union_field_vals, 0..) |*field_val, i| {
1629016555 const field = union_fields.values()[i];
16291 const name = union_fields.keys()[i];
16556 // TODO: write something like getCoercedInts to avoid needing to dupe
16557 const name = try sema.arena.dupe(u8, ip.stringToSlice(union_fields.keys()[i]));
1629216558 const name_val = v: {
1629316559 var anon_decl = try block.startAnonDecl();
1629416560 defer anon_decl.deinit();
16295 const bytes = try anon_decl.arena().dupeZ(u8, name);
16561 const new_decl_ty = try mod.arrayType(.{
16562 .len = name.len,
16563 .child = .u8_type,
16564 });
1629616565 const new_decl = try anon_decl.finish(
16297 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
16298 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16566 new_decl_ty,
16567 (try mod.intern(.{ .aggregate = .{
16568 .ty = new_decl_ty.toIntern(),
16569 .storage = .{ .bytes = name },
16570 } })).toValue(),
1629916571 0, // default alignment
1630016572 );
16301 break :v try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl);
16573 break :v try mod.intern(.{ .ptr = .{
16574 .ty = .slice_const_u8_type,
16575 .addr = .{ .decl = new_decl },
16576 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16577 } });
1630216578 };
1630316579
16304 const union_field_fields = try fields_anon_decl.arena().create([3]Value);
1630516580 const alignment = switch (layout) {
1630616581 .Auto, .Extern => try sema.unionFieldAlignment(field),
1630716582 .Packed => 0,
1630816583 };
1630916584
16310 union_field_fields.* = .{
16585 const union_field_fields = .{
1631116586 // name: []const u8,
1631216587 name_val,
1631316588 // type: type,
16314 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),
16589 field.ty.toIntern(),
1631516590 // alignment: comptime_int,
16316 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),
16591 (try mod.intValue(Type.comptime_int, alignment)).toIntern(),
1631716592 };
16318 field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), union_field_fields);
16593 field_val.* = try mod.intern(.{ .aggregate = .{
16594 .ty = union_field_ty.toIntern(),
16595 .storage = .{ .elems = &union_field_fields },
16596 } });
1631916597 }
1632016598
1632116599 const fields_val = v: {
16600 const array_fields_ty = try mod.arrayType(.{
16601 .len = union_field_vals.len,
16602 .child = union_field_ty.toIntern(),
16603 .sentinel = .none,
16604 });
1632216605 const new_decl = try fields_anon_decl.finish(
16323 try Type.Tag.array.create(fields_anon_decl.arena(), .{
16324 .len = union_field_vals.len,
16325 .elem_type = union_field_ty,
16326 }),
16327 try Value.Tag.aggregate.create(
16328 fields_anon_decl.arena(),
16329 try fields_anon_decl.arena().dupe(Value, union_field_vals),
16330 ),
16606 array_fields_ty,
16607 (try mod.intern(.{ .aggregate = .{
16608 .ty = array_fields_ty.toIntern(),
16609 .storage = .{ .elems = union_field_vals },
16610 } })).toValue(),
1633116611 0, // default alignment
1633216612 );
16333 break :v try Value.Tag.slice.create(sema.arena, .{
16334 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16335 .len = try Value.Tag.int_u64.create(sema.arena, union_field_vals.len),
16336 });
16613 break :v try mod.intern(.{ .ptr = .{
16614 .ty = (try mod.ptrType(.{
16615 .child = union_field_ty.toIntern(),
16616 .flags = .{
16617 .size = .Slice,
16618 .is_const = true,
16619 },
16620 })).toIntern(),
16621 .addr = .{ .decl = new_decl },
16622 .len = (try mod.intValue(Type.usize, union_field_vals.len)).toIntern(),
16623 } });
1633716624 };
1633816625
16339 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespace());
16626 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, union_ty.getNamespaceIndex(mod));
1634016627
16341 const enum_tag_ty_val = if (union_ty.unionTagType()) |tag_ty| v: {
16342 const ty_val = try Value.Tag.ty.create(sema.arena, tag_ty);
16343 break :v try Value.Tag.opt_payload.create(sema.arena, ty_val);
16344 } else Value.null;
16628 const enum_tag_ty_val = try mod.intern(.{ .opt = .{
16629 .ty = (try mod.optionalType(.type_type)).toIntern(),
16630 .val = if (union_ty.unionTagType(mod)) |tag_ty| tag_ty.toIntern() else .none,
16631 } });
16632
16633 const container_layout_ty = t: {
16634 const decl_index = (try sema.namespaceLookup(
16635 block,
16636 src,
16637 (try sema.getBuiltinType("Type")).getNamespaceIndex(mod).unwrap().?,
16638 try ip.getOrPutString(gpa, "ContainerLayout"),
16639 )).?;
16640 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
16641 try sema.ensureDeclAnalyzed(decl_index);
16642 const decl = mod.declPtr(decl_index);
16643 break :t decl.val.toType();
16644 };
1634516645
16346 const field_values = try sema.arena.create([4]Value);
16347 field_values.* = .{
16646 const field_values = .{
1634816647 // layout: ContainerLayout,
16349 try Value.Tag.enum_field_index.create(
16350 sema.arena,
16351 @enumToInt(layout),
16352 ),
16648 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).toIntern(),
1635316649
1635416650 // tag_type: ?type,
1635516651 enum_tag_ty_val,
......@@ -16358,14 +16654,14 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1635816654 // decls: []const Declaration,
1635916655 decls_val,
1636016656 };
16361
16362 return sema.addConstant(
16363 type_info_ty,
16364 try Value.Tag.@"union".create(sema.arena, .{
16365 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Union)),
16366 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16367 }),
16368 );
16657 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16658 .ty = type_info_ty.toIntern(),
16659 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Union))).toIntern(),
16660 .val = try mod.intern(.{ .aggregate = .{
16661 .ty = type_union_ty.toIntern(),
16662 .storage = .{ .elems = &field_values },
16663 } }),
16664 } })).toValue());
1636916665 },
1637016666 .Struct => {
1637116667 // TODO: look into memoizing this result.
......@@ -16373,154 +16669,212 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1637316669 var fields_anon_decl = try block.startAnonDecl();
1637416670 defer fields_anon_decl.deinit();
1637516671
16376 const struct_field_ty = t: {
16377 const struct_field_ty_decl_index = (try sema.namespaceLookup(
16672 const type_struct_ty = t: {
16673 const type_struct_ty_decl_index = (try sema.namespaceLookup(
1637816674 block,
1637916675 src,
16380 type_info_ty.getNamespace().?,
16381 "StructField",
16676 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16677 try ip.getOrPutString(gpa, "Struct"),
1638216678 )).?;
16383 try sema.mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index);
16384 try sema.ensureDeclAnalyzed(struct_field_ty_decl_index);
16385 const struct_field_ty_decl = sema.mod.declPtr(struct_field_ty_decl_index);
16386 var buffer: Value.ToTypeBuffer = undefined;
16387 break :t try struct_field_ty_decl.val.toType(&buffer).copy(fields_anon_decl.arena());
16679 try mod.declareDeclDependency(sema.owner_decl_index, type_struct_ty_decl_index);
16680 try sema.ensureDeclAnalyzed(type_struct_ty_decl_index);
16681 const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index);
16682 break :t type_struct_ty_decl.val.toType();
1638816683 };
16389 const struct_ty = try sema.resolveTypeFields(ty);
16390 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16391 const layout = struct_ty.containerLayout();
16392
16393 const struct_field_vals = fv: {
16394 if (struct_ty.isSimpleTupleOrAnonStruct()) {
16395 const tuple = struct_ty.tupleFields();
16396 const field_types = tuple.types;
16397 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
16398 for (struct_field_vals, 0..) |*struct_field_val, i| {
16399 const field_ty = field_types[i];
16400 const name_val = v: {
16401 var anon_decl = try block.startAnonDecl();
16402 defer anon_decl.deinit();
16403 const bytes = if (struct_ty.castTag(.anon_struct)) |payload|
16404 try anon_decl.arena().dupeZ(u8, payload.data.names[i])
16405 else
16406 try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
16407 const new_decl = try anon_decl.finish(
16408 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
16409 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16410 0, // default alignment
16411 );
16412 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
16413 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16414 .len = try Value.Tag.int_u64.create(fields_anon_decl.arena(), bytes.len),
16415 });
16416 };
1641716684
16418 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16419 const field_val = tuple.values[i];
16420 const is_comptime = field_val.tag() != .unreachable_value;
16421 const opt_default_val = if (is_comptime) field_val else null;
16422 const default_val_ptr = try sema.optRefValue(block, field_ty, opt_default_val);
16423 struct_field_fields.* = .{
16424 // name: []const u8,
16425 name_val,
16426 // type: type,
16427 try Value.Tag.ty.create(fields_anon_decl.arena(), field_ty),
16428 // default_value: ?*const anyopaque,
16429 try default_val_ptr.copy(fields_anon_decl.arena()),
16430 // is_comptime: bool,
16431 Value.makeBool(is_comptime),
16432 // alignment: comptime_int,
16433 try field_ty.lazyAbiAlignment(target, fields_anon_decl.arena()),
16434 };
16435 struct_field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16436 }
16437 break :fv struct_field_vals;
16438 }
16439 const struct_fields = struct_ty.structFields();
16440 const struct_field_vals = try fields_anon_decl.arena().alloc(Value, struct_fields.count());
16685 const struct_field_ty = t: {
16686 const struct_field_ty_decl_index = (try sema.namespaceLookup(
16687 block,
16688 src,
16689 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16690 try ip.getOrPutString(gpa, "StructField"),
16691 )).?;
16692 try mod.declareDeclDependency(sema.owner_decl_index, struct_field_ty_decl_index);
16693 try sema.ensureDeclAnalyzed(struct_field_ty_decl_index);
16694 const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);
16695 break :t struct_field_ty_decl.val.toType();
16696 };
16697
16698 const struct_ty = try sema.resolveTypeFields(ty);
16699 try sema.resolveTypeLayout(ty); // Getting alignment requires type layout
16700 const layout = struct_ty.containerLayout(mod);
16701
16702 var struct_field_vals: []InternPool.Index = &.{};
16703 defer gpa.free(struct_field_vals);
16704 fv: {
16705 const struct_type = switch (ip.indexToKey(struct_ty.toIntern())) {
16706 .anon_struct_type => |tuple| {
16707 struct_field_vals = try gpa.alloc(InternPool.Index, tuple.types.len);
16708 for (struct_field_vals, 0..) |*struct_field_val, i| {
16709 const anon_struct_type = ip.indexToKey(struct_ty.toIntern()).anon_struct_type;
16710 const field_ty = anon_struct_type.types[i];
16711 const field_val = anon_struct_type.values[i];
16712 const name_val = v: {
16713 var anon_decl = try block.startAnonDecl();
16714 defer anon_decl.deinit();
16715 // TODO: write something like getCoercedInts to avoid needing to dupe
16716 const bytes = if (tuple.names.len != 0)
16717 // https://github.com/ziglang/zig/issues/15709
16718 try sema.arena.dupe(u8, ip.stringToSlice(ip.indexToKey(struct_ty.toIntern()).anon_struct_type.names[i]))
16719 else
16720 try std.fmt.allocPrint(sema.arena, "{d}", .{i});
16721 const new_decl_ty = try mod.arrayType(.{
16722 .len = bytes.len,
16723 .child = .u8_type,
16724 });
16725 const new_decl = try anon_decl.finish(
16726 new_decl_ty,
16727 (try mod.intern(.{ .aggregate = .{
16728 .ty = new_decl_ty.toIntern(),
16729 .storage = .{ .bytes = bytes },
16730 } })).toValue(),
16731 0, // default alignment
16732 );
16733 break :v try mod.intern(.{ .ptr = .{
16734 .ty = .slice_const_u8_type,
16735 .addr = .{ .decl = new_decl },
16736 .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(),
16737 } });
16738 };
1644116739
16442 for (struct_field_vals, 0..) |*field_val, i| {
16443 const field = struct_fields.values()[i];
16444 const name = struct_fields.keys()[i];
16740 const is_comptime = field_val != .none;
16741 const opt_default_val = if (is_comptime) field_val.toValue() else null;
16742 const default_val_ptr = try sema.optRefValue(block, field_ty.toType(), opt_default_val);
16743 const struct_field_fields = .{
16744 // name: []const u8,
16745 name_val,
16746 // type: type,
16747 field_ty,
16748 // default_value: ?*const anyopaque,
16749 default_val_ptr.toIntern(),
16750 // is_comptime: bool,
16751 Value.makeBool(is_comptime).toIntern(),
16752 // alignment: comptime_int,
16753 (try mod.intValue(Type.comptime_int, field_ty.toType().abiAlignment(mod))).toIntern(),
16754 };
16755 struct_field_val.* = try mod.intern(.{ .aggregate = .{
16756 .ty = struct_field_ty.toIntern(),
16757 .storage = .{ .elems = &struct_field_fields },
16758 } });
16759 }
16760 break :fv;
16761 },
16762 .struct_type => |s| s,
16763 else => unreachable,
16764 };
16765 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :fv;
16766 struct_field_vals = try gpa.alloc(InternPool.Index, struct_obj.fields.count());
16767
16768 for (
16769 struct_field_vals,
16770 struct_obj.fields.keys(),
16771 struct_obj.fields.values(),
16772 ) |*field_val, name_nts, field| {
16773 // TODO: write something like getCoercedInts to avoid needing to dupe
16774 const name = try sema.arena.dupe(u8, ip.stringToSlice(name_nts));
1644516775 const name_val = v: {
1644616776 var anon_decl = try block.startAnonDecl();
1644716777 defer anon_decl.deinit();
16448 const bytes = try anon_decl.arena().dupeZ(u8, name);
16778 const new_decl_ty = try mod.arrayType(.{
16779 .len = name.len,
16780 .child = .u8_type,
16781 });
1644916782 const new_decl = try anon_decl.finish(
16450 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
16451 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
16783 new_decl_ty,
16784 (try mod.intern(.{ .aggregate = .{
16785 .ty = new_decl_ty.toIntern(),
16786 .storage = .{ .bytes = name },
16787 } })).toValue(),
1645216788 0, // default alignment
1645316789 );
16454 break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{
16455 .ptr = try Value.Tag.decl_ref.create(fields_anon_decl.arena(), new_decl),
16456 .len = try Value.Tag.int_u64.create(fields_anon_decl.arena(), bytes.len),
16457 });
16790 break :v try mod.intern(.{ .ptr = .{
16791 .ty = .slice_const_u8_type,
16792 .addr = .{ .decl = new_decl },
16793 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
16794 } });
1645816795 };
1645916796
16460 const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
16461 const opt_default_val = if (field.default_val.tag() == .unreachable_value)
16797 const opt_default_val = if (field.default_val == .none)
1646216798 null
1646316799 else
16464 field.default_val;
16800 field.default_val.toValue();
1646516801 const default_val_ptr = try sema.optRefValue(block, field.ty, opt_default_val);
16466 const alignment = field.alignment(target, layout);
16802 const alignment = field.alignment(mod, layout);
1646716803
16468 struct_field_fields.* = .{
16804 const struct_field_fields = .{
1646916805 // name: []const u8,
1647016806 name_val,
1647116807 // type: type,
16472 try Value.Tag.ty.create(fields_anon_decl.arena(), field.ty),
16808 field.ty.toIntern(),
1647316809 // default_value: ?*const anyopaque,
16474 try default_val_ptr.copy(fields_anon_decl.arena()),
16810 default_val_ptr.toIntern(),
1647516811 // is_comptime: bool,
16476 Value.makeBool(field.is_comptime),
16812 Value.makeBool(field.is_comptime).toIntern(),
1647716813 // alignment: comptime_int,
16478 try Value.Tag.int_u64.create(fields_anon_decl.arena(), alignment),
16814 (try mod.intValue(Type.comptime_int, alignment)).toIntern(),
1647916815 };
16480 field_val.* = try Value.Tag.aggregate.create(fields_anon_decl.arena(), struct_field_fields);
16816 field_val.* = try mod.intern(.{ .aggregate = .{
16817 .ty = struct_field_ty.toIntern(),
16818 .storage = .{ .elems = &struct_field_fields },
16819 } });
1648116820 }
16482 break :fv struct_field_vals;
16483 };
16821 }
1648416822
1648516823 const fields_val = v: {
16824 const array_fields_ty = try mod.arrayType(.{
16825 .len = struct_field_vals.len,
16826 .child = struct_field_ty.toIntern(),
16827 .sentinel = .none,
16828 });
1648616829 const new_decl = try fields_anon_decl.finish(
16487 try Type.Tag.array.create(fields_anon_decl.arena(), .{
16488 .len = struct_field_vals.len,
16489 .elem_type = struct_field_ty,
16490 }),
16491 try Value.Tag.aggregate.create(
16492 fields_anon_decl.arena(),
16493 try fields_anon_decl.arena().dupe(Value, struct_field_vals),
16494 ),
16830 array_fields_ty,
16831 (try mod.intern(.{ .aggregate = .{
16832 .ty = array_fields_ty.toIntern(),
16833 .storage = .{ .elems = struct_field_vals },
16834 } })).toValue(),
1649516835 0, // default alignment
1649616836 );
16497 break :v try Value.Tag.slice.create(sema.arena, .{
16498 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16499 .len = try Value.Tag.int_u64.create(sema.arena, struct_field_vals.len),
16500 });
16837 break :v try mod.intern(.{ .ptr = .{
16838 .ty = (try mod.ptrType(.{
16839 .child = struct_field_ty.toIntern(),
16840 .flags = .{
16841 .size = .Slice,
16842 .is_const = true,
16843 },
16844 })).toIntern(),
16845 .addr = .{ .decl = new_decl },
16846 .len = (try mod.intValue(Type.usize, struct_field_vals.len)).toIntern(),
16847 } });
1650116848 };
1650216849
16503 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespace());
16850 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, struct_ty.getNamespaceIndex(mod));
1650416851
16505 const backing_integer_val = blk: {
16506 if (layout == .Packed) {
16507 const struct_obj = struct_ty.castTag(.@"struct").?.data;
16852 const backing_integer_val = try mod.intern(.{ .opt = .{
16853 .ty = (try mod.optionalType(.type_type)).toIntern(),
16854 .val = if (layout == .Packed) val: {
16855 const struct_obj = mod.typeToStruct(struct_ty).?;
1650816856 assert(struct_obj.haveLayout());
16509 assert(struct_obj.backing_int_ty.isInt());
16510 const backing_int_ty_val = try Value.Tag.ty.create(sema.arena, struct_obj.backing_int_ty);
16511 break :blk try Value.Tag.opt_payload.create(sema.arena, backing_int_ty_val);
16512 } else {
16513 break :blk Value.initTag(.null_value);
16514 }
16857 assert(struct_obj.backing_int_ty.isInt(mod));
16858 break :val struct_obj.backing_int_ty.toIntern();
16859 } else .none,
16860 } });
16861
16862 const container_layout_ty = t: {
16863 const decl_index = (try sema.namespaceLookup(
16864 block,
16865 src,
16866 (try sema.getBuiltinType("Type")).getNamespaceIndex(mod).unwrap().?,
16867 try ip.getOrPutString(gpa, "ContainerLayout"),
16868 )).?;
16869 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
16870 try sema.ensureDeclAnalyzed(decl_index);
16871 const decl = mod.declPtr(decl_index);
16872 break :t decl.val.toType();
1651516873 };
1651616874
16517 const field_values = try sema.arena.create([5]Value);
16518 field_values.* = .{
16875 const field_values = [_]InternPool.Index{
1651916876 // layout: ContainerLayout,
16520 try Value.Tag.enum_field_index.create(
16521 sema.arena,
16522 @enumToInt(layout),
16523 ),
16877 (try mod.enumValueFieldIndex(container_layout_ty, @enumToInt(layout))).toIntern(),
1652416878 // backing_integer: ?type,
1652516879 backing_integer_val,
1652616880 // fields: []const StructField,
......@@ -16528,36 +16882,48 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1652816882 // decls: []const Declaration,
1652916883 decls_val,
1653016884 // is_tuple: bool,
16531 Value.makeBool(struct_ty.isTuple()),
16885 Value.makeBool(struct_ty.isTuple(mod)).toIntern(),
1653216886 };
16533
16534 return sema.addConstant(
16535 type_info_ty,
16536 try Value.Tag.@"union".create(sema.arena, .{
16537 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Struct)),
16538 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16539 }),
16540 );
16887 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16888 .ty = type_info_ty.toIntern(),
16889 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Struct))).toIntern(),
16890 .val = try mod.intern(.{ .aggregate = .{
16891 .ty = type_struct_ty.toIntern(),
16892 .storage = .{ .elems = &field_values },
16893 } }),
16894 } })).toValue());
1654116895 },
1654216896 .Opaque => {
1654316897 // TODO: look into memoizing this result.
1654416898
16899 const type_opaque_ty = t: {
16900 const type_opaque_ty_decl_index = (try sema.namespaceLookup(
16901 block,
16902 src,
16903 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16904 try ip.getOrPutString(gpa, "Opaque"),
16905 )).?;
16906 try mod.declareDeclDependency(sema.owner_decl_index, type_opaque_ty_decl_index);
16907 try sema.ensureDeclAnalyzed(type_opaque_ty_decl_index);
16908 const type_opaque_ty_decl = mod.declPtr(type_opaque_ty_decl_index);
16909 break :t type_opaque_ty_decl.val.toType();
16910 };
16911
1654516912 const opaque_ty = try sema.resolveTypeFields(ty);
16546 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespace());
16913 const decls_val = try sema.typeInfoDecls(block, src, type_info_ty, opaque_ty.getNamespaceIndex(mod));
1654716914
16548 const field_values = try sema.arena.create([1]Value);
16549 field_values.* = .{
16915 const field_values = .{
1655016916 // decls: []const Declaration,
1655116917 decls_val,
1655216918 };
16553
16554 return sema.addConstant(
16555 type_info_ty,
16556 try Value.Tag.@"union".create(sema.arena, .{
16557 .tag = try Value.Tag.enum_field_index.create(sema.arena, @enumToInt(std.builtin.TypeId.Opaque)),
16558 .val = try Value.Tag.aggregate.create(sema.arena, field_values),
16559 }),
16560 );
16919 return sema.addConstant(type_info_ty, (try mod.intern(.{ .un = .{
16920 .ty = type_info_ty.toIntern(),
16921 .tag = (try mod.enumValueFieldIndex(type_info_tag_ty, @enumToInt(std.builtin.TypeId.Opaque))).toIntern(),
16922 .val = try mod.intern(.{ .aggregate = .{
16923 .ty = type_opaque_ty.toIntern(),
16924 .storage = .{ .elems = &field_values },
16925 } }),
16926 } })).toValue());
1656116927 },
1656216928 .Frame => return sema.failWithUseOfAsync(block, src),
1656316929 .AnyFrame => return sema.failWithUseOfAsync(block, src),
......@@ -16569,8 +16935,11 @@ fn typeInfoDecls(
1656916935 block: *Block,
1657016936 src: LazySrcLoc,
1657116937 type_info_ty: Type,
16572 opt_namespace: ?*Module.Namespace,
16573) CompileError!Value {
16938 opt_namespace: Module.Namespace.OptionalIndex,
16939) CompileError!InternPool.Index {
16940 const mod = sema.mod;
16941 const gpa = sema.gpa;
16942
1657416943 var decls_anon_decl = try block.startAnonDecl();
1657516944 defer decls_anon_decl.deinit();
1657616945
......@@ -16578,89 +16947,110 @@ fn typeInfoDecls(
1657816947 const declaration_ty_decl_index = (try sema.namespaceLookup(
1657916948 block,
1658016949 src,
16581 type_info_ty.getNamespace().?,
16582 "Declaration",
16950 type_info_ty.getNamespaceIndex(mod).unwrap().?,
16951 try mod.intern_pool.getOrPutString(gpa, "Declaration"),
1658316952 )).?;
16584 try sema.mod.declareDeclDependency(sema.owner_decl_index, declaration_ty_decl_index);
16953 try mod.declareDeclDependency(sema.owner_decl_index, declaration_ty_decl_index);
1658516954 try sema.ensureDeclAnalyzed(declaration_ty_decl_index);
16586 const declaration_ty_decl = sema.mod.declPtr(declaration_ty_decl_index);
16587 var buffer: Value.ToTypeBuffer = undefined;
16588 break :t try declaration_ty_decl.val.toType(&buffer).copy(decls_anon_decl.arena());
16955 const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index);
16956 break :t declaration_ty_decl.val.toType();
1658916957 };
16590 try sema.queueFullTypeResolution(try declaration_ty.copy(sema.arena));
16958 try sema.queueFullTypeResolution(declaration_ty);
1659116959
16592 var decl_vals = std.ArrayList(Value).init(sema.gpa);
16960 var decl_vals = std.ArrayList(InternPool.Index).init(gpa);
1659316961 defer decl_vals.deinit();
1659416962
16595 var seen_namespaces = std.AutoHashMap(*Namespace, void).init(sema.gpa);
16963 var seen_namespaces = std.AutoHashMap(*Namespace, void).init(gpa);
1659616964 defer seen_namespaces.deinit();
1659716965
16598 if (opt_namespace) |some| {
16599 try sema.typeInfoNamespaceDecls(block, decls_anon_decl.arena(), some, &decl_vals, &seen_namespaces);
16966 if (opt_namespace.unwrap()) |namespace_index| {
16967 const namespace = mod.namespacePtr(namespace_index);
16968 try sema.typeInfoNamespaceDecls(block, namespace, declaration_ty, &decl_vals, &seen_namespaces);
1660016969 }
1660116970
16971 const array_decl_ty = try mod.arrayType(.{
16972 .len = decl_vals.items.len,
16973 .child = declaration_ty.toIntern(),
16974 .sentinel = .none,
16975 });
1660216976 const new_decl = try decls_anon_decl.finish(
16603 try Type.Tag.array.create(decls_anon_decl.arena(), .{
16604 .len = decl_vals.items.len,
16605 .elem_type = declaration_ty,
16606 }),
16607 try Value.Tag.aggregate.create(
16608 decls_anon_decl.arena(),
16609 try decls_anon_decl.arena().dupe(Value, decl_vals.items),
16610 ),
16977 array_decl_ty,
16978 (try mod.intern(.{ .aggregate = .{
16979 .ty = array_decl_ty.toIntern(),
16980 .storage = .{ .elems = decl_vals.items },
16981 } })).toValue(),
1661116982 0, // default alignment
1661216983 );
16613 return try Value.Tag.slice.create(sema.arena, .{
16614 .ptr = try Value.Tag.decl_ref.create(sema.arena, new_decl),
16615 .len = try Value.Tag.int_u64.create(sema.arena, decl_vals.items.len),
16616 });
16984 return try mod.intern(.{ .ptr = .{
16985 .ty = (try mod.ptrType(.{
16986 .child = declaration_ty.toIntern(),
16987 .flags = .{
16988 .size = .Slice,
16989 .is_const = true,
16990 },
16991 })).toIntern(),
16992 .addr = .{ .decl = new_decl },
16993 .len = (try mod.intValue(Type.usize, decl_vals.items.len)).toIntern(),
16994 } });
1661716995}
1661816996
1661916997fn typeInfoNamespaceDecls(
1662016998 sema: *Sema,
1662116999 block: *Block,
16622 decls_anon_decl: Allocator,
1662317000 namespace: *Namespace,
16624 decl_vals: *std.ArrayList(Value),
17001 declaration_ty: Type,
17002 decl_vals: *std.ArrayList(InternPool.Index),
1662517003 seen_namespaces: *std.AutoHashMap(*Namespace, void),
1662617004) !void {
17005 const mod = sema.mod;
17006 const ip = &mod.intern_pool;
1662717007 const gop = try seen_namespaces.getOrPut(namespace);
1662817008 if (gop.found_existing) return;
1662917009 const decls = namespace.decls.keys();
1663017010 for (decls) |decl_index| {
16631 const decl = sema.mod.declPtr(decl_index);
17011 const decl = mod.declPtr(decl_index);
1663217012 if (decl.kind == .@"usingnamespace") {
1663317013 if (decl.analysis == .in_progress) continue;
16634 try sema.mod.ensureDeclAnalyzed(decl_index);
16635 var buf: Value.ToTypeBuffer = undefined;
16636 const new_ns = decl.val.toType(&buf).getNamespace().?;
16637 try sema.typeInfoNamespaceDecls(block, decls_anon_decl, new_ns, decl_vals, seen_namespaces);
17014 try mod.ensureDeclAnalyzed(decl_index);
17015 const new_ns = decl.val.toType().getNamespace(mod).?;
17016 try sema.typeInfoNamespaceDecls(block, new_ns, declaration_ty, decl_vals, seen_namespaces);
1663817017 continue;
1663917018 }
1664017019 if (decl.kind != .named) continue;
1664117020 const name_val = v: {
1664217021 var anon_decl = try block.startAnonDecl();
1664317022 defer anon_decl.deinit();
16644 const bytes = try anon_decl.arena().dupeZ(u8, mem.sliceTo(decl.name, 0));
17023 // TODO: write something like getCoercedInts to avoid needing to dupe
17024 const name = try sema.arena.dupe(u8, ip.stringToSlice(decl.name));
17025 const new_decl_ty = try mod.arrayType(.{
17026 .len = name.len,
17027 .child = .u8_type,
17028 });
1664517029 const new_decl = try anon_decl.finish(
16646 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
16647 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
17030 new_decl_ty,
17031 (try mod.intern(.{ .aggregate = .{
17032 .ty = new_decl_ty.toIntern(),
17033 .storage = .{ .bytes = name },
17034 } })).toValue(),
1664817035 0, // default alignment
1664917036 );
16650 break :v try Value.Tag.slice.create(decls_anon_decl, .{
16651 .ptr = try Value.Tag.decl_ref.create(decls_anon_decl, new_decl),
16652 .len = try Value.Tag.int_u64.create(decls_anon_decl, bytes.len),
16653 });
17037 break :v try mod.intern(.{ .ptr = .{
17038 .ty = .slice_const_u8_type,
17039 .addr = .{ .decl = new_decl },
17040 .len = (try mod.intValue(Type.usize, name.len)).toIntern(),
17041 } });
1665417042 };
1665517043
16656 const fields = try decls_anon_decl.create([2]Value);
16657 fields.* = .{
17044 const fields = .{
1665817045 //name: []const u8,
1665917046 name_val,
1666017047 //is_pub: bool,
16661 Value.makeBool(decl.is_pub),
17048 Value.makeBool(decl.is_pub).toIntern(),
1666217049 };
16663 try decl_vals.append(try Value.Tag.aggregate.create(decls_anon_decl, fields));
17050 try decl_vals.append(try mod.intern(.{ .aggregate = .{
17051 .ty = declaration_ty.toIntern(),
17052 .storage = .{ .elems = &fields },
17053 } }));
1666417054 }
1666517055}
1666617056
......@@ -16695,7 +17085,7 @@ fn zirTypeofBuiltin(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
1669517085
1669617086 const operand = try sema.resolveBody(&child_block, body, inst);
1669717087 const operand_ty = sema.typeOf(operand);
16698 if (operand_ty.tag() == .generic_poison) return error.GenericPoison;
17088 if (operand_ty.isGenericPoison()) return error.GenericPoison;
1669917089 return sema.addType(operand_ty);
1670017090}
1670117091
......@@ -16709,10 +17099,11 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
1670917099}
1671017100
1671117101fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) CompileError!Type {
16712 switch (operand.zigTypeTag()) {
17102 const mod = sema.mod;
17103 switch (operand.zigTypeTag(mod)) {
1671317104 .ComptimeInt => return Type.comptime_int,
1671417105 .Int => {
16715 const bits = operand.bitSize(sema.mod.getTarget());
17106 const bits = operand.bitSize(mod);
1671617107 const count = if (bits == 0)
1671717108 0
1671817109 else blk: {
......@@ -16723,14 +17114,14 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
1672317114 }
1672417115 break :blk count;
1672517116 };
16726 return Module.makeIntType(sema.arena, .unsigned, count);
17117 return mod.intType(.unsigned, count);
1672717118 },
1672817119 .Vector => {
16729 const elem_ty = operand.elemType2();
17120 const elem_ty = operand.elemType2(mod);
1673017121 const log2_elem_ty = try sema.log2IntType(block, elem_ty, src);
16731 return Type.Tag.vector.create(sema.arena, .{
16732 .len = operand.vectorLen(),
16733 .elem_type = log2_elem_ty,
17122 return mod.vectorType(.{
17123 .len = operand.vectorLen(mod),
17124 .child = log2_elem_ty.toIntern(),
1673417125 });
1673517126 },
1673617127 else => {},
......@@ -16739,7 +17130,7 @@ fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) Compi
1673917130 block,
1674017131 src,
1674117132 "bit shifting operation expected integer type, found '{}'",
16742 .{operand.fmt(sema.mod)},
17133 .{operand.fmt(mod)},
1674317134 );
1674417135}
1674517136
......@@ -16790,6 +17181,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1679017181 const tracy = trace(@src());
1679117182 defer tracy.end();
1679217183
17184 const mod = sema.mod;
1679317185 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1679417186 const src = inst_data.src();
1679517187 const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node };
......@@ -16797,7 +17189,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1679717189
1679817190 const operand = try sema.coerce(block, Type.bool, uncasted_operand, operand_src);
1679917191 if (try sema.resolveMaybeUndefVal(operand)) |val| {
16800 return if (val.isUndef())
17192 return if (val.isUndef(mod))
1680117193 sema.addConstUndef(Type.bool)
1680217194 else if (val.toBool())
1680317195 Air.Inst.Ref.bool_false
......@@ -16817,6 +17209,7 @@ fn zirBoolBr(
1681717209 const tracy = trace(@src());
1681817210 defer tracy.end();
1681917211
17212 const mod = sema.mod;
1682017213 const datas = sema.code.instructions.items(.data);
1682117214 const inst_data = datas[inst].bool_br;
1682217215 const lhs = try sema.resolveInst(inst_data.lhs);
......@@ -16865,12 +17258,12 @@ fn zirBoolBr(
1686517258 _ = try lhs_block.addBr(block_inst, lhs_result);
1686617259
1686717260 const rhs_result = try sema.resolveBody(rhs_block, body, inst);
16868 if (!sema.typeOf(rhs_result).isNoReturn()) {
17261 if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
1686917262 _ = try rhs_block.addBr(block_inst, rhs_result);
1687017263 }
1687117264
1687217265 const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
16873 if (!sema.typeOf(rhs_result).isNoReturn()) {
17266 if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
1687417267 if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| {
1687517268 if (is_bool_or and rhs_val.toBool()) {
1687617269 return Air.Inst.Ref.bool_true;
......@@ -16920,9 +17313,10 @@ fn finishCondBr(
1692017313}
1692117314
1692217315fn checkNullableType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
16923 switch (ty.zigTypeTag()) {
17316 const mod = sema.mod;
17317 switch (ty.zigTypeTag(mod)) {
1692417318 .Optional, .Null, .Undefined => return,
16925 .Pointer => if (ty.isPtrLikeOptional()) return,
17319 .Pointer => if (ty.isPtrLikeOptional(mod)) return,
1692617320 else => {},
1692717321 }
1692817322 return sema.failWithExpectedOptionalType(block, src, ty);
......@@ -16951,10 +17345,11 @@ fn zirIsNonNullPtr(
1695117345 const tracy = trace(@src());
1695217346 defer tracy.end();
1695317347
17348 const mod = sema.mod;
1695417349 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1695517350 const src = inst_data.src();
1695617351 const ptr = try sema.resolveInst(inst_data.operand);
16957 try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2());
17352 try sema.checkNullableType(block, src, sema.typeOf(ptr).elemType2(mod));
1695817353 if ((try sema.resolveMaybeUndefVal(ptr)) == null) {
1695917354 return block.addUnOp(.is_non_null_ptr, ptr);
1696017355 }
......@@ -16963,10 +17358,11 @@ fn zirIsNonNullPtr(
1696317358}
1696417359
1696517360fn checkErrorType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
16966 switch (ty.zigTypeTag()) {
17361 const mod = sema.mod;
17362 switch (ty.zigTypeTag(mod)) {
1696717363 .ErrorSet, .ErrorUnion, .Undefined => return,
1696817364 else => return sema.fail(block, src, "expected error union type, found '{}'", .{
16969 ty.fmt(sema.mod),
17365 ty.fmt(mod),
1697017366 }),
1697117367 }
1697217368}
......@@ -16986,10 +17382,11 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
1698617382 const tracy = trace(@src());
1698717383 defer tracy.end();
1698817384
17385 const mod = sema.mod;
1698917386 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1699017387 const src = inst_data.src();
1699117388 const ptr = try sema.resolveInst(inst_data.operand);
16992 try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2());
17389 try sema.checkErrorType(block, src, sema.typeOf(ptr).elemType2(mod));
1699317390 const loaded = try sema.analyzeLoad(block, src, ptr, src);
1699417391 return sema.analyzeIsNonErr(block, src, loaded);
1699517392}
......@@ -17012,6 +17409,7 @@ fn zirCondbr(
1701217409 const tracy = trace(@src());
1701317410 defer tracy.end();
1701417411
17412 const mod = sema.mod;
1701517413 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1701617414 const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node };
1701717415 const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index);
......@@ -17052,8 +17450,8 @@ fn zirCondbr(
1705217450 const err_inst_data = sema.code.instructions.items(.data)[index].un_node;
1705317451 const err_operand = try sema.resolveInst(err_inst_data.operand);
1705417452 const operand_ty = sema.typeOf(err_operand);
17055 assert(operand_ty.zigTypeTag() == .ErrorUnion);
17056 const result_ty = operand_ty.errorUnionSet();
17453 assert(operand_ty.zigTypeTag(mod) == .ErrorUnion);
17454 const result_ty = operand_ty.errorUnionSet(mod);
1705717455 break :blk try sub_block.addTyOp(.unwrap_errunion_err, result_ty, err_operand);
1705817456 };
1705917457
......@@ -17079,7 +17477,7 @@ fn zirCondbr(
1707917477 return always_noreturn;
1708017478}
1708117479
17082fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref {
17480fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1708317481 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1708417482 const src = inst_data.src();
1708517483 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
......@@ -17087,9 +17485,10 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1708717485 const body = sema.code.extra[extra.end..][0..extra.data.body_len];
1708817486 const err_union = try sema.resolveInst(extra.data.operand);
1708917487 const err_union_ty = sema.typeOf(err_union);
17090 if (err_union_ty.zigTypeTag() != .ErrorUnion) {
17488 const mod = sema.mod;
17489 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) {
1709117490 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{
17092 err_union_ty.fmt(sema.mod),
17491 err_union_ty.fmt(mod),
1709317492 });
1709417493 }
1709517494 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
......@@ -17124,7 +17523,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!
1712417523 return try_inst;
1712517524}
1712617525
17127fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Ref {
17526fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
1712817527 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1712917528 const src = inst_data.src();
1713017529 const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
......@@ -17133,9 +17532,10 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1713317532 const operand = try sema.resolveInst(extra.data.operand);
1713417533 const err_union = try sema.analyzeLoad(parent_block, src, operand, operand_src);
1713517534 const err_union_ty = sema.typeOf(err_union);
17136 if (err_union_ty.zigTypeTag() != .ErrorUnion) {
17535 const mod = sema.mod;
17536 if (err_union_ty.zigTypeTag(mod) != .ErrorUnion) {
1713717537 return sema.fail(parent_block, operand_src, "expected error union type, found '{}'", .{
17138 err_union_ty.fmt(sema.mod),
17538 err_union_ty.fmt(mod),
1713917539 });
1714017540 }
1714117541 const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union);
......@@ -17156,9 +17556,9 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
1715617556 _ = try sema.analyzeBodyInner(&sub_block, body);
1715717557
1715817558 const operand_ty = sema.typeOf(operand);
17159 const ptr_info = operand_ty.ptrInfo().data;
17160 const res_ty = try Type.ptr(sema.arena, sema.mod, .{
17161 .pointee_type = err_union_ty.errorUnionPayload(),
17559 const ptr_info = operand_ty.ptrInfo(mod);
17560 const res_ty = try Type.ptr(sema.arena, mod, .{
17561 .pointee_type = err_union_ty.errorUnionPayload(mod),
1716217562 .@"addrspace" = ptr_info.@"addrspace",
1716317563 .mutable = ptr_info.mutable,
1716417564 .@"allowzero" = ptr_info.@"allowzero",
......@@ -17254,16 +17654,17 @@ fn zirRetErrValue(
1725417654 block: *Block,
1725517655 inst: Zir.Inst.Index,
1725617656) CompileError!Zir.Inst.Index {
17657 const mod = sema.mod;
1725717658 const inst_data = sema.code.instructions.items(.data)[inst].str_tok;
17258 const err_name = inst_data.get(sema.code);
17659 const err_name = try mod.intern_pool.getOrPutString(sema.gpa, inst_data.get(sema.code));
17660 _ = try mod.getErrorValue(err_name);
1725917661 const src = inst_data.src();
17260
1726117662 // Return the error code from the function.
17262 const kv = try sema.mod.getErrorValue(err_name);
17263 const result_inst = try sema.addConstant(
17264 try Type.Tag.error_set_single.create(sema.arena, kv.key),
17265 try Value.Tag.@"error".create(sema.arena, .{ .name = kv.key }),
17266 );
17663 const error_set_type = try mod.singleErrorSetType(err_name);
17664 const result_inst = try sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
17665 .ty = error_set_type.toIntern(),
17666 .name = err_name,
17667 } })).toValue());
1726717668 return sema.analyzeRet(block, result_inst, src);
1726817669}
1726917670
......@@ -17275,16 +17676,17 @@ fn zirRetImplicit(
1727517676 const tracy = trace(@src());
1727617677 defer tracy.end();
1727717678
17679 const mod = sema.mod;
1727817680 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
1727917681 const operand = try sema.resolveInst(inst_data.operand);
1728017682
1728117683 const r_brace_src = inst_data.src();
1728217684 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
17283 const base_tag = sema.fn_ret_ty.baseZigTypeTag();
17685 const base_tag = sema.fn_ret_ty.baseZigTypeTag(mod);
1728417686 if (base_tag == .NoReturn) {
1728517687 const msg = msg: {
1728617688 const msg = try sema.errMsg(block, ret_ty_src, "function declared '{}' implicitly returns", .{
17287 sema.fn_ret_ty.fmt(sema.mod),
17689 sema.fn_ret_ty.fmt(mod),
1728817690 });
1728917691 errdefer msg.destroy(sema.gpa);
1729017692 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});
......@@ -17294,7 +17696,7 @@ fn zirRetImplicit(
1729417696 } else if (base_tag != .Void) {
1729517697 const msg = msg: {
1729617698 const msg = try sema.errMsg(block, ret_ty_src, "function with non-void return type '{}' implicitly returns", .{
17297 sema.fn_ret_ty.fmt(sema.mod),
17699 sema.fn_ret_ty.fmt(mod),
1729817700 });
1729917701 errdefer msg.destroy(sema.gpa);
1730017702 try sema.errNote(block, r_brace_src, msg, "control flow reaches end of body here", .{});
......@@ -17346,6 +17748,7 @@ fn retWithErrTracing(
1734617748 ret_tag: Air.Inst.Tag,
1734717749 operand: Air.Inst.Ref,
1734817750) CompileError!Zir.Inst.Index {
17751 const mod = sema.mod;
1734917752 const need_check = switch (is_non_err) {
1735017753 .bool_true => {
1735117754 _ = try block.addUnOp(ret_tag, operand);
......@@ -17357,7 +17760,7 @@ fn retWithErrTracing(
1735717760 const gpa = sema.gpa;
1735817761 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
1735917762 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
17360 const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty);
17763 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
1736117764 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
1736217765 const return_err_fn = try sema.getBuiltin("returnError");
1736317766 const args: [1]Air.Inst.Ref = .{err_return_trace};
......@@ -17397,17 +17800,19 @@ fn retWithErrTracing(
1739717800}
1739817801
1739917802fn wantErrorReturnTracing(sema: *Sema, fn_ret_ty: Type) bool {
17400 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return false;
17803 const mod = sema.mod;
17804 if (!mod.backendSupportsFeature(.error_return_trace)) return false;
1740117805
17402 return fn_ret_ty.isError() and
17403 sema.mod.comp.bin_file.options.error_return_tracing;
17806 return fn_ret_ty.isError(mod) and
17807 mod.comp.bin_file.options.error_return_tracing;
1740417808}
1740517809
1740617810fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
17811 const mod = sema.mod;
1740717812 const inst_data = sema.code.instructions.items(.data)[inst].save_err_ret_index;
1740817813
17409 if (!sema.mod.backendSupportsFeature(.error_return_trace)) return;
17410 if (!sema.mod.comp.bin_file.options.error_return_tracing) return;
17814 if (!mod.backendSupportsFeature(.error_return_trace)) return;
17815 if (!mod.comp.bin_file.options.error_return_tracing) return;
1741117816
1741217817 // This is only relevant at runtime.
1741317818 if (block.is_comptime or block.is_typeof) return;
......@@ -17415,7 +17820,7 @@ fn zirSaveErrRetIndex(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1741517820 const save_index = inst_data.operand == .none or b: {
1741617821 const operand = try sema.resolveInst(inst_data.operand);
1741717822 const operand_ty = sema.typeOf(operand);
17418 break :b operand_ty.isError();
17823 break :b operand_ty.isError(mod);
1741917824 };
1742017825
1742117826 if (save_index)
......@@ -17436,7 +17841,7 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1743617841 const tracy = trace(@src());
1743717842 defer tracy.end();
1743817843
17439 const saved_index = if (Zir.refToIndex(inst_data.block)) |zir_block| b: {
17844 const saved_index = if (Zir.refToIndexAllowNone(inst_data.block)) |zir_block| b: {
1744017845 var block = start_block;
1744117846 while (true) {
1744217847 if (block.label) |label| {
......@@ -17462,22 +17867,21 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
1746217867
1746317868 assert(saved_index != .none); // The .error_return_trace_index field was dropped somewhere
1746417869
17465 const operand = try sema.resolveInst(inst_data.operand);
17870 const operand = try sema.resolveInstAllowNone(inst_data.operand);
1746617871 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);
1746717872}
1746817873
1746917874fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
17470 assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);
17875 const mod = sema.mod;
17876 const gpa = sema.gpa;
17877 const ip = &mod.intern_pool;
17878 assert(sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion);
1747117879
17472 if (sema.fn_ret_ty.errorUnionSet().castTag(.error_set_inferred)) |payload| {
17880 if (mod.typeToInferredErrorSet(sema.fn_ret_ty.errorUnionSet(mod))) |ies| {
1747317881 const op_ty = sema.typeOf(uncasted_operand);
17474 switch (op_ty.zigTypeTag()) {
17475 .ErrorSet => {
17476 try payload.data.addErrorSet(sema.gpa, op_ty);
17477 },
17478 .ErrorUnion => {
17479 try payload.data.addErrorSet(sema.gpa, op_ty.errorUnionSet());
17480 },
17882 switch (op_ty.zigTypeTag(mod)) {
17883 .ErrorSet => try ies.addErrorSet(op_ty, ip, gpa),
17884 .ErrorUnion => try ies.addErrorSet(op_ty.errorUnionSet(mod), ip, gpa),
1748117885 else => {},
1748217886 }
1748317887 }
......@@ -17492,7 +17896,8 @@ fn analyzeRet(
1749217896 // Special case for returning an error to an inferred error set; we need to
1749317897 // add the error tag to the inferred error set of the in-scope function, so
1749417898 // that the coercion below works correctly.
17495 if (sema.fn_ret_ty.zigTypeTag() == .ErrorUnion) {
17899 const mod = sema.mod;
17900 if (sema.fn_ret_ty.zigTypeTag(mod) == .ErrorUnion) {
1749617901 try sema.addToInferredErrorSet(uncasted_operand);
1749717902 }
1749817903 const operand = sema.coerceExtra(block, sema.fn_ret_ty, uncasted_operand, src, .{ .is_ret = true }) catch |err| switch (err) {
......@@ -17540,6 +17945,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1754017945 const tracy = trace(@src());
1754117946 defer tracy.end();
1754217947
17948 const mod = sema.mod;
1754317949 const inst_data = sema.code.instructions.items(.data)[inst].ptr_type;
1754417950 const extra = sema.code.extraData(Zir.Inst.PtrType, inst_data.payload_index);
1754517951 const elem_ty_src: LazySrcLoc = .{ .node_offset_ptr_elem = extra.data.src_node };
......@@ -17552,46 +17958,54 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1755217958 const elem_ty = blk: {
1755317959 const air_inst = try sema.resolveInst(extra.data.elem_type);
1755417960 const ty = sema.analyzeAsType(block, elem_ty_src, air_inst) catch |err| {
17555 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer()) {
17961 if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(mod)) {
1755617962 try sema.errNote(block, elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{});
1755717963 }
1755817964 return err;
1755917965 };
17560 if (ty.tag() == .generic_poison) return error.GenericPoison;
17966 if (ty.isGenericPoison()) return error.GenericPoison;
1756117967 break :blk ty;
1756217968 };
17563 const target = sema.mod.getTarget();
17969
17970 if (elem_ty.zigTypeTag(mod) == .NoReturn)
17971 return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{});
17972
17973 const target = mod.getTarget();
1756417974
1756517975 var extra_i = extra.end;
1756617976
1756717977 const sentinel = if (inst_data.flags.has_sentinel) blk: {
1756817978 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
1756917979 extra_i += 1;
17570 break :blk (try sema.resolveInstConst(block, sentinel_src, ref, "pointer sentinel value must be comptime-known")).val;
17571 } else null;
17980 const coerced = try sema.coerce(block, elem_ty, try sema.resolveInst(ref), sentinel_src);
17981 const val = try sema.resolveConstValue(block, sentinel_src, coerced, "pointer sentinel value must be comptime-known");
17982 break :blk val.toIntern();
17983 } else .none;
1757217984
17573 const abi_align: u32 = if (inst_data.flags.has_align) blk: {
17985 const abi_align: InternPool.Alignment = if (inst_data.flags.has_align) blk: {
1757417986 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
1757517987 extra_i += 1;
1757617988 const coerced = try sema.coerce(block, Type.u32, try sema.resolveInst(ref), align_src);
1757717989 const val = try sema.resolveConstValue(block, align_src, coerced, "pointer alignment must be comptime-known");
1757817990 // Check if this happens to be the lazy alignment of our element type, in
1757917991 // which case we can make this 0 without resolving it.
17580 if (val.castTag(.lazy_align)) |payload| {
17581 if (payload.data.eql(elem_ty, sema.mod)) {
17582 break :blk 0;
17583 }
17992 switch (mod.intern_pool.indexToKey(val.toIntern())) {
17993 .int => |int| switch (int.storage) {
17994 .lazy_align => |lazy_ty| if (lazy_ty == elem_ty.toIntern()) break :blk .none,
17995 else => {},
17996 },
17997 else => {},
1758417998 }
17585 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(target, sema)).?);
17999 const abi_align = @intCast(u32, (try val.getUnsignedIntAdvanced(mod, sema)).?);
1758618000 try sema.validateAlign(block, align_src, abi_align);
17587 break :blk abi_align;
17588 } else 0;
18001 break :blk InternPool.Alignment.fromByteUnits(abi_align);
18002 } else .none;
1758918003
1759018004 const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {
1759118005 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
1759218006 extra_i += 1;
1759318007 break :blk try sema.analyzeAddressSpace(block, addrspace_src, ref, .pointer);
17594 } else if (elem_ty.zigTypeTag() == .Fn and target.cpu.arch == .avr) .flash else .generic;
18008 } else if (elem_ty.zigTypeTag(mod) == .Fn and target.cpu.arch == .avr) .flash else .generic;
1759518009
1759618010 const bit_offset = if (inst_data.flags.has_bit_range) blk: {
1759718011 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
......@@ -17611,50 +18025,52 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1761118025 return sema.fail(block, bitoffset_src, "bit offset starts after end of host integer", .{});
1761218026 }
1761318027
17614 if (elem_ty.zigTypeTag() == .NoReturn) {
17615 return sema.fail(block, elem_ty_src, "pointer to noreturn not allowed", .{});
17616 } else if (elem_ty.zigTypeTag() == .Fn) {
18028 if (elem_ty.zigTypeTag(mod) == .Fn) {
1761718029 if (inst_data.size != .One) {
1761818030 return sema.fail(block, elem_ty_src, "function pointers must be single pointers", .{});
1761918031 }
17620 const fn_align = elem_ty.fnInfo().alignment;
17621 if (inst_data.flags.has_align and abi_align != 0 and fn_align != 0 and
18032 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
18033 if (inst_data.flags.has_align and abi_align != .none and fn_align != .none and
1762218034 abi_align != fn_align)
1762318035 {
1762418036 return sema.fail(block, align_src, "function pointer alignment disagrees with function alignment", .{});
1762518037 }
17626 } else if (inst_data.size == .Many and elem_ty.zigTypeTag() == .Opaque) {
18038 } else if (inst_data.size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
1762718039 return sema.fail(block, elem_ty_src, "unknown-length pointer to opaque not allowed", .{});
1762818040 } else if (inst_data.size == .C) {
1762918041 if (!try sema.validateExternType(elem_ty, .other)) {
1763018042 const msg = msg: {
17631 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
18043 const msg = try sema.errMsg(block, elem_ty_src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)});
1763218044 errdefer msg.destroy(sema.gpa);
1763318045
17634 const src_decl = sema.mod.declPtr(block.src_decl);
17635 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl), elem_ty, .other);
18046 const src_decl = mod.declPtr(block.src_decl);
18047 try sema.explainWhyTypeIsNotExtern(msg, elem_ty_src.toSrcLoc(src_decl, mod), elem_ty, .other);
1763618048
1763718049 try sema.addDeclaredHereNote(msg, elem_ty);
1763818050 break :msg msg;
1763918051 };
1764018052 return sema.failWithOwnedErrorMsg(msg);
1764118053 }
17642 if (elem_ty.zigTypeTag() == .Opaque) {
18054 if (elem_ty.zigTypeTag(mod) == .Opaque) {
1764318055 return sema.fail(block, elem_ty_src, "C pointers cannot point to opaque types", .{});
1764418056 }
1764518057 }
1764618058
17647 const ty = try Type.ptr(sema.arena, sema.mod, .{
17648 .pointee_type = elem_ty,
18059 const ty = try mod.ptrType(.{
18060 .child = elem_ty.toIntern(),
1764918061 .sentinel = sentinel,
17650 .@"align" = abi_align,
17651 .@"addrspace" = address_space,
17652 .bit_offset = bit_offset,
17653 .host_size = host_size,
17654 .mutable = inst_data.flags.is_mutable,
17655 .@"allowzero" = inst_data.flags.is_allowzero,
17656 .@"volatile" = inst_data.flags.is_volatile,
17657 .size = inst_data.size,
18062 .flags = .{
18063 .alignment = abi_align,
18064 .address_space = address_space,
18065 .is_const = !inst_data.flags.is_mutable,
18066 .is_allowzero = inst_data.flags.is_allowzero,
18067 .is_volatile = inst_data.flags.is_volatile,
18068 .size = inst_data.size,
18069 },
18070 .packed_offset = .{
18071 .bit_offset = bit_offset,
18072 .host_size = host_size,
18073 },
1765818074 });
1765918075 return sema.addType(ty);
1766018076}
......@@ -17666,8 +18082,9 @@ fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1766618082 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1766718083 const src = inst_data.src();
1766818084 const obj_ty = try sema.resolveType(block, src, inst_data.operand);
18085 const mod = sema.mod;
1766918086
17670 switch (obj_ty.zigTypeTag()) {
18087 switch (obj_ty.zigTypeTag(mod)) {
1767118088 .Struct => return sema.structInitEmpty(block, obj_ty, src, src),
1767218089 .Array, .Vector => return sema.arrayInitEmpty(block, src, obj_ty),
1767318090 .Void => return sema.addConstant(obj_ty, Value.void),
......@@ -17683,12 +18100,13 @@ fn structInitEmpty(
1768318100 dest_src: LazySrcLoc,
1768418101 init_src: LazySrcLoc,
1768518102) CompileError!Air.Inst.Ref {
18103 const mod = sema.mod;
1768618104 const gpa = sema.gpa;
1768718105 // This logic must be synchronized with that in `zirStructInit`.
1768818106 const struct_ty = try sema.resolveTypeFields(obj_ty);
1768918107
1769018108 // The init values to use for the struct instance.
17691 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount());
18109 const field_inits = try gpa.alloc(Air.Inst.Ref, struct_ty.structFieldCount(mod));
1769218110 defer gpa.free(field_inits);
1769318111 @memset(field_inits, .none);
1769418112
......@@ -17696,20 +18114,19 @@ fn structInitEmpty(
1769618114}
1769718115
1769818116fn arrayInitEmpty(sema: *Sema, block: *Block, src: LazySrcLoc, obj_ty: Type) CompileError!Air.Inst.Ref {
17699 const arr_len = obj_ty.arrayLen();
18117 const mod = sema.mod;
18118 const arr_len = obj_ty.arrayLen(mod);
1770018119 if (arr_len != 0) {
17701 if (obj_ty.zigTypeTag() == .Array) {
18120 if (obj_ty.zigTypeTag(mod) == .Array) {
1770218121 return sema.fail(block, src, "expected {d} array elements; found 0", .{arr_len});
1770318122 } else {
1770418123 return sema.fail(block, src, "expected {d} vector elements; found 0", .{arr_len});
1770518124 }
1770618125 }
17707 if (obj_ty.sentinel()) |sentinel| {
17708 const val = try Value.Tag.empty_array_sentinel.create(sema.arena, sentinel);
17709 return sema.addConstant(obj_ty, val);
17710 } else {
17711 return sema.addConstant(obj_ty, Value.initTag(.empty_array));
17712 }
18126 return sema.addConstant(obj_ty, (try mod.intern(.{ .aggregate = .{
18127 .ty = obj_ty.toIntern(),
18128 .storage = .{ .elems = &.{} },
18129 } })).toValue());
1771318130}
1771418131
1771518132fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -17719,7 +18136,7 @@ fn zirUnionInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1771918136 const init_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
1772018137 const extra = sema.code.extraData(Zir.Inst.UnionInit, inst_data.payload_index).data;
1772118138 const union_ty = try sema.resolveType(block, ty_src, extra.union_type);
17722 const field_name = try sema.resolveConstString(block, field_src, extra.field_name, "name of field being initialized must be comptime-known");
18139 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, "name of field being initialized must be comptime-known");
1772318140 const init = try sema.resolveInst(extra.init);
1772418141 return sema.unionInit(block, init, init_src, union_ty, ty_src, field_name, field_src);
1772518142}
......@@ -17731,21 +18148,23 @@ fn unionInit(
1773118148 init_src: LazySrcLoc,
1773218149 union_ty: Type,
1773318150 union_ty_src: LazySrcLoc,
17734 field_name: []const u8,
18151 field_name: InternPool.NullTerminatedString,
1773518152 field_src: LazySrcLoc,
1773618153) CompileError!Air.Inst.Ref {
18154 const mod = sema.mod;
1773718155 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_src);
17738 const field = union_ty.unionFields().values()[field_index];
18156 const field = union_ty.unionFields(mod).values()[field_index];
1773918157 const init = try sema.coerce(block, field.ty, uncasted_init, init_src);
1774018158
1774118159 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
17742 const tag_ty = union_ty.unionTagTypeHypothetical();
17743 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);
17744 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);
17745 return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{
17746 .tag = tag_val,
17747 .val = init_val,
17748 }));
18160 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
18161 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
18162 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
18163 return sema.addConstant(union_ty, (try mod.intern(.{ .un = .{
18164 .ty = union_ty.toIntern(),
18165 .tag = try tag_val.intern(tag_ty, mod),
18166 .val = try init_val.intern(field.ty, mod),
18167 } })).toValue());
1774918168 }
1775018169
1775118170 try sema.requireRuntimeBlock(block, init_src, null);
......@@ -17766,29 +18185,30 @@ fn zirStructInit(
1776618185 const extra = sema.code.extraData(Zir.Inst.StructInit, inst_data.payload_index);
1776718186 const src = inst_data.src();
1776818187
18188 const mod = sema.mod;
1776918189 const first_item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end).data;
1777018190 const first_field_type_data = zir_datas[first_item.field_type].pl_node;
1777118191 const first_field_type_extra = sema.code.extraData(Zir.Inst.FieldType, first_field_type_data.payload_index).data;
1777218192 const resolved_ty = try sema.resolveType(block, src, first_field_type_extra.container_type);
1777318193 try sema.resolveTypeLayout(resolved_ty);
1777418194
17775 if (resolved_ty.zigTypeTag() == .Struct) {
18195 if (resolved_ty.zigTypeTag(mod) == .Struct) {
1777618196 // This logic must be synchronized with that in `zirStructInitEmpty`.
1777718197
1777818198 // Maps field index to field_type index of where it was already initialized.
1777918199 // For making sure all fields are accounted for and no fields are duplicated.
17780 const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount());
18200 const found_fields = try gpa.alloc(Zir.Inst.Index, resolved_ty.structFieldCount(mod));
1778118201 defer gpa.free(found_fields);
1778218202
1778318203 // The init values to use for the struct instance.
17784 const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount());
18204 const field_inits = try gpa.alloc(Air.Inst.Ref, resolved_ty.structFieldCount(mod));
1778518205 defer gpa.free(field_inits);
1778618206 @memset(field_inits, .none);
1778718207
1778818208 var field_i: u32 = 0;
1778918209 var extra_index = extra.end;
1779018210
17791 const is_packed = resolved_ty.containerLayout() == .Packed;
18211 const is_packed = resolved_ty.containerLayout(mod) == .Packed;
1779218212 while (field_i < extra.data.fields_len) : (field_i += 1) {
1779318213 const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra_index);
1779418214 extra_index = item.end;
......@@ -17796,8 +18216,8 @@ fn zirStructInit(
1779618216 const field_type_data = zir_datas[item.data.field_type].pl_node;
1779718217 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
1779818218 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
17799 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
17800 const field_index = if (resolved_ty.isTuple())
18219 const field_name = try mod.intern_pool.getOrPutString(gpa, sema.code.nullTerminatedString(field_type_extra.name_start));
18220 const field_index = if (resolved_ty.isTuple(mod))
1780118221 try sema.tupleFieldIndex(block, resolved_ty, field_name, field_src)
1780218222 else
1780318223 try sema.structFieldIndex(block, resolved_ty, field_name, field_src);
......@@ -17815,19 +18235,19 @@ fn zirStructInit(
1781518235 }
1781618236 found_fields[field_index] = item.data.field_type;
1781718237 field_inits[field_index] = try sema.resolveInst(item.data.init);
17818 if (!is_packed) if (resolved_ty.structFieldValueComptime(field_index)) |default_value| {
18238 if (!is_packed) if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {
1781918239 const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {
1782018240 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
1782118241 };
1782218242
17823 if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index), sema.mod)) {
18243 if (!init_val.eql(default_value, resolved_ty.structFieldType(field_index, mod), mod)) {
1782418244 return sema.failWithInvalidComptimeFieldStore(block, field_src, resolved_ty, field_index);
1782518245 }
1782618246 };
1782718247 }
1782818248
1782918249 return sema.finishStructInit(block, src, src, field_inits, resolved_ty, is_ref);
17830 } else if (resolved_ty.zigTypeTag() == .Union) {
18250 } else if (resolved_ty.zigTypeTag(mod) == .Union) {
1783118251 if (extra.data.fields_len != 1) {
1783218252 return sema.fail(block, src, "union initialization expects exactly one field", .{});
1783318253 }
......@@ -17837,32 +18257,32 @@ fn zirStructInit(
1783718257 const field_type_data = zir_datas[item.data.field_type].pl_node;
1783818258 const field_src: LazySrcLoc = .{ .node_offset_initializer = field_type_data.src_node };
1783918259 const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
17840 const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
18260 const field_name = try mod.intern_pool.getOrPutString(gpa, sema.code.nullTerminatedString(field_type_extra.name_start));
1784118261 const field_index = try sema.unionFieldIndex(block, resolved_ty, field_name, field_src);
17842 const tag_ty = resolved_ty.unionTagTypeHypothetical();
17843 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);
17844 const tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);
18262 const tag_ty = resolved_ty.unionTagTypeHypothetical(mod);
18263 const enum_field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name, mod).?);
18264 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
1784518265
1784618266 const init_inst = try sema.resolveInst(item.data.init);
1784718267 if (try sema.resolveMaybeUndefVal(init_inst)) |val| {
17848 return sema.addConstantMaybeRef(
17849 block,
17850 resolved_ty,
17851 try Value.Tag.@"union".create(sema.arena, .{ .tag = tag_val, .val = val }),
17852 is_ref,
17853 );
18268 const field = resolved_ty.unionFields(mod).values()[field_index];
18269 return sema.addConstantMaybeRef(block, resolved_ty, (try mod.intern(.{ .un = .{
18270 .ty = resolved_ty.toIntern(),
18271 .tag = try tag_val.intern(tag_ty, mod),
18272 .val = try val.intern(field.ty, mod),
18273 } })).toValue(), is_ref);
1785418274 }
1785518275
1785618276 if (is_ref) {
17857 const target = sema.mod.getTarget();
17858 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18277 const target = mod.getTarget();
18278 const alloc_ty = try Type.ptr(sema.arena, mod, .{
1785918279 .pointee_type = resolved_ty,
1786018280 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1786118281 });
1786218282 const alloc = try block.addTy(.alloc, alloc_ty);
1786318283 const field_ptr = try sema.unionFieldPtr(block, field_src, alloc, field_name, field_src, resolved_ty, true);
1786418284 try sema.storePtr(block, src, field_ptr, init_inst);
17865 const new_tag = try sema.addConstant(resolved_ty.unionTagTypeHypothetical(), tag_val);
18285 const new_tag = try sema.addConstant(resolved_ty.unionTagTypeHypothetical(mod), tag_val);
1786618286 _ = try block.addBinOp(.set_union_tag, alloc, new_tag);
1786718287 return sema.makePtrConst(block, alloc);
1786818288 }
......@@ -17870,7 +18290,7 @@ fn zirStructInit(
1787018290 try sema.requireRuntimeBlock(block, src, null);
1787118291 try sema.queueFullTypeResolution(resolved_ty);
1787218292 return block.addUnionInit(resolved_ty, field_index, init_inst);
17873 } else if (resolved_ty.isAnonStruct()) {
18293 } else if (resolved_ty.isAnonStruct(mod)) {
1787418294 return sema.fail(block, src, "TODO anon struct init validation", .{});
1787518295 }
1787618296 unreachable;
......@@ -17885,76 +18305,70 @@ fn finishStructInit(
1788518305 struct_ty: Type,
1788618306 is_ref: bool,
1788718307) CompileError!Air.Inst.Ref {
17888 const gpa = sema.gpa;
18308 const mod = sema.mod;
18309 const ip = &mod.intern_pool;
1788918310
1789018311 var root_msg: ?*Module.ErrorMsg = null;
1789118312 errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
1789218313
17893 if (struct_ty.isAnonStruct()) {
17894 const struct_obj = struct_ty.castTag(.anon_struct).?.data;
17895 for (struct_obj.values, 0..) |default_val, i| {
17896 if (field_inits[i] != .none) continue;
17897
17898 if (default_val.tag() == .unreachable_value) {
17899 const field_name = struct_obj.names[i];
17900 const template = "missing struct field: {s}";
17901 const args = .{field_name};
17902 if (root_msg) |msg| {
17903 try sema.errNote(block, init_src, msg, template, args);
17904 } else {
17905 root_msg = try sema.errMsg(block, init_src, template, args);
17906 }
17907 } else {
17908 field_inits[i] = try sema.addConstant(struct_obj.types[i], default_val);
17909 }
17910 }
17911 } else if (struct_ty.isTuple()) {
17912 var i: u32 = 0;
17913 const len = struct_ty.structFieldCount();
17914 while (i < len) : (i += 1) {
17915 if (field_inits[i] != .none) continue;
18314 switch (ip.indexToKey(struct_ty.toIntern())) {
18315 .anon_struct_type => |anon_struct| {
18316 for (anon_struct.types, anon_struct.values, 0..) |field_ty, default_val, i| {
18317 if (field_inits[i] != .none) continue;
1791618318
17917 const default_val = struct_ty.structFieldDefaultValue(i);
17918 if (default_val.tag() == .unreachable_value) {
17919 const template = "missing tuple field with index {d}";
17920 if (root_msg) |msg| {
17921 try sema.errNote(block, init_src, msg, template, .{i});
18319 if (default_val == .none) {
18320 if (anon_struct.names.len == 0) {
18321 const template = "missing tuple field with index {d}";
18322 if (root_msg) |msg| {
18323 try sema.errNote(block, init_src, msg, template, .{i});
18324 } else {
18325 root_msg = try sema.errMsg(block, init_src, template, .{i});
18326 }
18327 } else {
18328 const field_name = anon_struct.names[i];
18329 const template = "missing struct field: {}";
18330 const args = .{field_name.fmt(ip)};
18331 if (root_msg) |msg| {
18332 try sema.errNote(block, init_src, msg, template, args);
18333 } else {
18334 root_msg = try sema.errMsg(block, init_src, template, args);
18335 }
18336 }
1792218337 } else {
17923 root_msg = try sema.errMsg(block, init_src, template, .{i});
18338 field_inits[i] = try sema.addConstant(field_ty.toType(), default_val.toValue());
1792418339 }
17925 } else {
17926 field_inits[i] = try sema.addConstant(struct_ty.structFieldType(i), default_val);
1792718340 }
17928 }
17929 } else {
17930 const struct_obj = struct_ty.castTag(.@"struct").?.data;
17931 for (struct_obj.fields.values(), 0..) |field, i| {
17932 if (field_inits[i] != .none) continue;
18341 },
18342 .struct_type => |struct_type| {
18343 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18344 for (struct_obj.fields.values(), 0..) |field, i| {
18345 if (field_inits[i] != .none) continue;
1793318346
17934 if (field.default_val.tag() == .unreachable_value) {
17935 const field_name = struct_obj.fields.keys()[i];
17936 const template = "missing struct field: {s}";
17937 const args = .{field_name};
17938 if (root_msg) |msg| {
17939 try sema.errNote(block, init_src, msg, template, args);
18347 if (field.default_val == .none) {
18348 const field_name = struct_obj.fields.keys()[i];
18349 const template = "missing struct field: {}";
18350 const args = .{field_name.fmt(ip)};
18351 if (root_msg) |msg| {
18352 try sema.errNote(block, init_src, msg, template, args);
18353 } else {
18354 root_msg = try sema.errMsg(block, init_src, template, args);
18355 }
1794018356 } else {
17941 root_msg = try sema.errMsg(block, init_src, template, args);
18357 field_inits[i] = try sema.addConstant(field.ty, field.default_val.toValue());
1794218358 }
17943 } else {
17944 field_inits[i] = try sema.addConstant(field.ty, field.default_val);
1794518359 }
17946 }
18360 },
18361 else => unreachable,
1794718362 }
1794818363
1794918364 if (root_msg) |msg| {
17950 if (struct_ty.castTag(.@"struct")) |struct_obj| {
17951 const fqn = try struct_obj.data.getFullyQualifiedName(sema.mod);
17952 defer gpa.free(fqn);
17953 try sema.mod.errNoteNonLazy(
17954 struct_obj.data.srcLoc(sema.mod),
18365 if (mod.typeToStruct(struct_ty)) |struct_obj| {
18366 const fqn = try struct_obj.getFullyQualifiedName(mod);
18367 try mod.errNoteNonLazy(
18368 struct_obj.srcLoc(mod),
1795518369 msg,
17956 "struct '{s}' declared here",
17957 .{fqn},
18370 "struct '{}' declared here",
18371 .{fqn.fmt(ip)},
1795818372 );
1795918373 }
1796018374 root_msg = null;
......@@ -17969,18 +18383,22 @@ fn finishStructInit(
1796918383 } else null;
1797018384
1797118385 const runtime_index = opt_runtime_index orelse {
17972 const values = try sema.arena.alloc(Value, field_inits.len);
17973 for (field_inits, 0..) |field_init, i| {
17974 values[i] = (sema.resolveMaybeUndefVal(field_init) catch unreachable).?;
17975 }
17976 const struct_val = try Value.Tag.aggregate.create(sema.arena, values);
17977 return sema.addConstantMaybeRef(block, struct_ty, struct_val, is_ref);
18386 const elems = try sema.arena.alloc(InternPool.Index, field_inits.len);
18387 for (elems, field_inits, 0..) |*elem, field_init, field_i| {
18388 elem.* = try (sema.resolveMaybeUndefVal(field_init) catch unreachable).?
18389 .intern(struct_ty.structFieldType(field_i, mod), mod);
18390 }
18391 const struct_val = try mod.intern(.{ .aggregate = .{
18392 .ty = struct_ty.toIntern(),
18393 .storage = .{ .elems = elems },
18394 } });
18395 return sema.addConstantMaybeRef(block, struct_ty, struct_val.toValue(), is_ref);
1797818396 };
1797918397
1798018398 if (is_ref) {
1798118399 try sema.resolveStructLayout(struct_ty);
1798218400 const target = sema.mod.getTarget();
17983 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18401 const alloc_ty = try Type.ptr(sema.arena, mod, .{
1798418402 .pointee_type = struct_ty,
1798518403 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1798618404 });
......@@ -17997,8 +18415,8 @@ fn finishStructInit(
1799718415
1799818416 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
1799918417 error.NeededSourceLocation => {
18000 const decl = sema.mod.declPtr(block.src_decl);
18001 const field_src = Module.initSrc(dest_src.node_offset.x, sema.gpa, decl, runtime_index);
18418 const decl = mod.declPtr(block.src_decl);
18419 const field_src = mod.initSrc(dest_src.node_offset.x, decl, runtime_index);
1800218420 try sema.requireRuntimeBlock(block, dest_src, field_src);
1800318421 unreachable;
1800418422 },
......@@ -18014,79 +18432,85 @@ fn zirStructInitAnon(
1801418432 inst: Zir.Inst.Index,
1801518433 is_ref: bool,
1801618434) CompileError!Air.Inst.Ref {
18435 const mod = sema.mod;
18436 const gpa = sema.gpa;
1801718437 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1801818438 const src = inst_data.src();
1801918439 const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
18020 const types = try sema.arena.alloc(Type, extra.data.fields_len);
18021 const values = try sema.arena.alloc(Value, types.len);
18022 var fields = std.StringArrayHashMapUnmanaged(u32){};
18023 defer fields.deinit(sema.gpa);
18024 try fields.ensureUnusedCapacity(sema.gpa, types.len);
18440 const types = try sema.arena.alloc(InternPool.Index, extra.data.fields_len);
18441 const values = try sema.arena.alloc(InternPool.Index, types.len);
18442 var fields = std.AutoArrayHashMap(InternPool.NullTerminatedString, u32).init(sema.arena);
18443 try fields.ensureUnusedCapacity(types.len);
1802518444
1802618445 // Find which field forces the expression to be runtime, if any.
1802718446 const opt_runtime_index = rs: {
1802818447 var runtime_index: ?usize = null;
1802918448 var extra_index = extra.end;
18030 for (types, 0..) |*field_ty, i| {
18449 for (types, 0..) |*field_ty, i_usize| {
18450 const i = @intCast(u32, i_usize);
1803118451 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
1803218452 extra_index = item.end;
1803318453
1803418454 const name = sema.code.nullTerminatedString(item.data.field_name);
18035 const gop = fields.getOrPutAssumeCapacity(name);
18455 const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
18456 const gop = fields.getOrPutAssumeCapacity(name_ip);
1803618457 if (gop.found_existing) {
1803718458 const msg = msg: {
18038 const decl = sema.mod.declPtr(block.src_decl);
18039 const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);
18459 const decl = mod.declPtr(block.src_decl);
18460 const field_src = mod.initSrc(src.node_offset.x, decl, i);
1804018461 const msg = try sema.errMsg(block, field_src, "duplicate field", .{});
18041 errdefer msg.destroy(sema.gpa);
18462 errdefer msg.destroy(gpa);
1804218463
18043 const prev_source = Module.initSrc(src.node_offset.x, sema.gpa, decl, gop.value_ptr.*);
18464 const prev_source = mod.initSrc(src.node_offset.x, decl, gop.value_ptr.*);
1804418465 try sema.errNote(block, prev_source, msg, "other field here", .{});
1804518466 break :msg msg;
1804618467 };
1804718468 return sema.failWithOwnedErrorMsg(msg);
1804818469 }
18049 gop.value_ptr.* = @intCast(u32, i);
18470 gop.value_ptr.* = i;
1805018471
1805118472 const init = try sema.resolveInst(item.data.init);
18052 field_ty.* = sema.typeOf(init);
18053 if (types[i].zigTypeTag() == .Opaque) {
18473 field_ty.* = sema.typeOf(init).toIntern();
18474 if (field_ty.toType().zigTypeTag(mod) == .Opaque) {
1805418475 const msg = msg: {
18055 const decl = sema.mod.declPtr(block.src_decl);
18056 const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);
18476 const decl = mod.declPtr(block.src_decl);
18477 const field_src = mod.initSrc(src.node_offset.x, decl, i);
1805718478 const msg = try sema.errMsg(block, field_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
1805818479 errdefer msg.destroy(sema.gpa);
1805918480
18060 try sema.addDeclaredHereNote(msg, types[i]);
18481 try sema.addDeclaredHereNote(msg, field_ty.toType());
1806118482 break :msg msg;
1806218483 };
1806318484 return sema.failWithOwnedErrorMsg(msg);
1806418485 }
1806518486 if (try sema.resolveMaybeUndefVal(init)) |init_val| {
18066 values[i] = init_val;
18487 values[i] = try init_val.intern(field_ty.toType(), mod);
1806718488 } else {
18068 values[i] = Value.initTag(.unreachable_value);
18489 values[i] = .none;
1806918490 runtime_index = i;
1807018491 }
1807118492 }
1807218493 break :rs runtime_index;
1807318494 };
1807418495
18075 const tuple_ty = try Type.Tag.anon_struct.create(sema.arena, .{
18076 .names = try sema.arena.dupe([]const u8, fields.keys()),
18496 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
18497 .names = fields.keys(),
1807718498 .types = types,
1807818499 .values = values,
18079 });
18500 } });
1808018501
1808118502 const runtime_index = opt_runtime_index orelse {
18082 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
18083 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);
18503 const tuple_val = try mod.intern(.{ .aggregate = .{
18504 .ty = tuple_ty,
18505 .storage = .{ .elems = values },
18506 } });
18507 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1808418508 };
1808518509
1808618510 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
1808718511 error.NeededSourceLocation => {
18088 const decl = sema.mod.declPtr(block.src_decl);
18089 const field_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, runtime_index);
18512 const decl = mod.declPtr(block.src_decl);
18513 const field_src = mod.initSrc(src.node_offset.x, decl, runtime_index);
1809018514 try sema.requireRuntimeBlock(block, src, field_src);
1809118515 unreachable;
1809218516 },
......@@ -18094,9 +18518,9 @@ fn zirStructInitAnon(
1809418518 };
1809518519
1809618520 if (is_ref) {
18097 const target = sema.mod.getTarget();
18098 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18099 .pointee_type = tuple_ty,
18521 const target = mod.getTarget();
18522 const alloc_ty = try Type.ptr(sema.arena, mod, .{
18523 .pointee_type = tuple_ty.toType(),
1810018524 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1810118525 });
1810218526 const alloc = try block.addTy(.alloc, alloc_ty);
......@@ -18106,12 +18530,12 @@ fn zirStructInitAnon(
1810618530 const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
1810718531 extra_index = item.end;
1810818532
18109 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18533 const field_ptr_ty = try Type.ptr(sema.arena, mod, .{
1811018534 .mutable = true,
1811118535 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18112 .pointee_type = field_ty,
18536 .pointee_type = field_ty.toType(),
1811318537 });
18114 if (values[i].tag() == .unreachable_value) {
18538 if (values[i] == .none) {
1811518539 const init = try sema.resolveInst(item.data.init);
1811618540 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
1811718541 _ = try block.addBinOp(.store, field_ptr, init);
......@@ -18129,7 +18553,7 @@ fn zirStructInitAnon(
1812918553 element_refs[i] = try sema.resolveInst(item.data.init);
1813018554 }
1813118555
18132 return block.addAggregateInit(tuple_ty, element_refs);
18556 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1813318557}
1813418558
1813518559fn zirArrayInit(
......@@ -18138,6 +18562,7 @@ fn zirArrayInit(
1813818562 inst: Zir.Inst.Index,
1813918563 is_ref: bool,
1814018564) CompileError!Air.Inst.Ref {
18565 const mod = sema.mod;
1814118566 const gpa = sema.gpa;
1814218567 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1814318568 const src = inst_data.src();
......@@ -18147,20 +18572,20 @@ fn zirArrayInit(
1814718572 assert(args.len >= 2); // array_ty + at least one element
1814818573
1814918574 const array_ty = try sema.resolveType(block, src, args[0]);
18150 const sentinel_val = array_ty.sentinel();
18575 const sentinel_val = array_ty.sentinel(mod);
1815118576
1815218577 const resolved_args = try gpa.alloc(Air.Inst.Ref, args.len - 1 + @boolToInt(sentinel_val != null));
1815318578 defer gpa.free(resolved_args);
1815418579 for (args[1..], 0..) |arg, i| {
1815518580 const resolved_arg = try sema.resolveInst(arg);
18156 const elem_ty = if (array_ty.zigTypeTag() == .Struct)
18157 array_ty.structFieldType(i)
18581 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)
18582 array_ty.structFieldType(i, mod)
1815818583 else
18159 array_ty.elemType2();
18584 array_ty.elemType2(mod);
1816018585 resolved_args[i] = sema.coerce(block, elem_ty, resolved_arg, .unneeded) catch |err| switch (err) {
1816118586 error.NeededSourceLocation => {
18162 const decl = sema.mod.declPtr(block.src_decl);
18163 const elem_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, i);
18587 const decl = mod.declPtr(block.src_decl);
18588 const elem_src = mod.initSrc(src.node_offset.x, decl, i);
1816418589 _ = try sema.coerce(block, elem_ty, resolved_arg, elem_src);
1816518590 unreachable;
1816618591 },
......@@ -18169,7 +18594,7 @@ fn zirArrayInit(
1816918594 }
1817018595
1817118596 if (sentinel_val) |some| {
18172 resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(), some);
18597 resolved_args[resolved_args.len - 1] = try sema.addConstant(array_ty.elemType2(mod), some);
1817318598 }
1817418599
1817518600 const opt_runtime_index: ?u32 = for (resolved_args, 0..) |arg, i| {
......@@ -18178,21 +18603,25 @@ fn zirArrayInit(
1817818603 } else null;
1817918604
1818018605 const runtime_index = opt_runtime_index orelse {
18181 const elem_vals = try sema.arena.alloc(Value, resolved_args.len);
18182
18183 for (resolved_args, 0..) |arg, i| {
18606 const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len);
18607 for (elem_vals, resolved_args, 0..) |*val, arg, i| {
18608 const elem_ty = if (array_ty.zigTypeTag(mod) == .Struct)
18609 array_ty.structFieldType(i, mod)
18610 else
18611 array_ty.elemType2(mod);
1818418612 // We checked that all args are comptime above.
18185 elem_vals[i] = (sema.resolveMaybeUndefVal(arg) catch unreachable).?;
18613 val.* = try ((sema.resolveMaybeUndefVal(arg) catch unreachable).?).intern(elem_ty, mod);
1818618614 }
18187
18188 const array_val = try Value.Tag.aggregate.create(sema.arena, elem_vals);
18189 return sema.addConstantMaybeRef(block, array_ty, array_val, is_ref);
18615 return sema.addConstantMaybeRef(block, array_ty, (try mod.intern(.{ .aggregate = .{
18616 .ty = array_ty.toIntern(),
18617 .storage = .{ .elems = elem_vals },
18618 } })).toValue(), is_ref);
1819018619 };
1819118620
1819218621 sema.requireRuntimeBlock(block, .unneeded, null) catch |err| switch (err) {
1819318622 error.NeededSourceLocation => {
18194 const decl = sema.mod.declPtr(block.src_decl);
18195 const elem_src = Module.initSrc(src.node_offset.x, sema.gpa, decl, runtime_index);
18623 const decl = mod.declPtr(block.src_decl);
18624 const elem_src = mod.initSrc(src.node_offset.x, decl, runtime_index);
1819618625 try sema.requireRuntimeBlock(block, src, elem_src);
1819718626 unreachable;
1819818627 },
......@@ -18201,19 +18630,19 @@ fn zirArrayInit(
1820118630 try sema.queueFullTypeResolution(array_ty);
1820218631
1820318632 if (is_ref) {
18204 const target = sema.mod.getTarget();
18205 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18633 const target = mod.getTarget();
18634 const alloc_ty = try Type.ptr(sema.arena, mod, .{
1820618635 .pointee_type = array_ty,
1820718636 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1820818637 });
1820918638 const alloc = try block.addTy(.alloc, alloc_ty);
1821018639
18211 if (array_ty.isTuple()) {
18640 if (array_ty.isTuple(mod)) {
1821218641 for (resolved_args, 0..) |arg, i| {
18213 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18642 const elem_ptr_ty = try Type.ptr(sema.arena, mod, .{
1821418643 .mutable = true,
1821518644 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18216 .pointee_type = array_ty.structFieldType(i),
18645 .pointee_type = array_ty.structFieldType(i, mod),
1821718646 });
1821818647 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1821918648
......@@ -18224,10 +18653,10 @@ fn zirArrayInit(
1822418653 return sema.makePtrConst(block, alloc);
1822518654 }
1822618655
18227 const elem_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
18656 const elem_ptr_ty = try Type.ptr(sema.arena, mod, .{
1822818657 .mutable = true,
1822918658 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18230 .pointee_type = array_ty.elemType2(),
18659 .pointee_type = array_ty.elemType2(mod),
1823118660 });
1823218661 const elem_ptr_ty_ref = try sema.addType(elem_ptr_ty);
1823318662
......@@ -18252,44 +18681,49 @@ fn zirArrayInitAnon(
1825218681 const src = inst_data.src();
1825318682 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
1825418683 const operands = sema.code.refSlice(extra.end, extra.data.operands_len);
18684 const mod = sema.mod;
1825518685
18256 const types = try sema.arena.alloc(Type, operands.len);
18257 const values = try sema.arena.alloc(Value, operands.len);
18686 const types = try sema.arena.alloc(InternPool.Index, operands.len);
18687 const values = try sema.arena.alloc(InternPool.Index, operands.len);
1825818688
1825918689 const opt_runtime_src = rs: {
1826018690 var runtime_src: ?LazySrcLoc = null;
1826118691 for (operands, 0..) |operand, i| {
1826218692 const operand_src = src; // TODO better source location
1826318693 const elem = try sema.resolveInst(operand);
18264 types[i] = sema.typeOf(elem);
18265 if (types[i].zigTypeTag() == .Opaque) {
18694 types[i] = sema.typeOf(elem).toIntern();
18695 if (types[i].toType().zigTypeTag(mod) == .Opaque) {
1826618696 const msg = msg: {
1826718697 const msg = try sema.errMsg(block, operand_src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
1826818698 errdefer msg.destroy(sema.gpa);
1826918699
18270 try sema.addDeclaredHereNote(msg, types[i]);
18700 try sema.addDeclaredHereNote(msg, types[i].toType());
1827118701 break :msg msg;
1827218702 };
1827318703 return sema.failWithOwnedErrorMsg(msg);
1827418704 }
1827518705 if (try sema.resolveMaybeUndefVal(elem)) |val| {
18276 values[i] = val;
18706 values[i] = val.toIntern();
1827718707 } else {
18278 values[i] = Value.initTag(.unreachable_value);
18708 values[i] = .none;
1827918709 runtime_src = operand_src;
1828018710 }
1828118711 }
1828218712 break :rs runtime_src;
1828318713 };
1828418714
18285 const tuple_ty = try Type.Tag.tuple.create(sema.arena, .{
18715 const tuple_ty = try mod.intern(.{ .anon_struct_type = .{
1828618716 .types = types,
1828718717 .values = values,
18288 });
18718 .names = &.{},
18719 } });
1828918720
1829018721 const runtime_src = opt_runtime_src orelse {
18291 const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
18292 return sema.addConstantMaybeRef(block, tuple_ty, tuple_val, is_ref);
18722 const tuple_val = try mod.intern(.{ .aggregate = .{
18723 .ty = tuple_ty,
18724 .storage = .{ .elems = values },
18725 } });
18726 return sema.addConstantMaybeRef(block, tuple_ty.toType(), tuple_val.toValue(), is_ref);
1829318727 };
1829418728
1829518729 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -18297,7 +18731,7 @@ fn zirArrayInitAnon(
1829718731 if (is_ref) {
1829818732 const target = sema.mod.getTarget();
1829918733 const alloc_ty = try Type.ptr(sema.arena, sema.mod, .{
18300 .pointee_type = tuple_ty,
18734 .pointee_type = tuple_ty.toType(),
1830118735 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
1830218736 });
1830318737 const alloc = try block.addTy(.alloc, alloc_ty);
......@@ -18306,9 +18740,9 @@ fn zirArrayInitAnon(
1830618740 const field_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
1830718741 .mutable = true,
1830818742 .@"addrspace" = target_util.defaultAddressSpace(target, .local),
18309 .pointee_type = types[i],
18743 .pointee_type = types[i].toType(),
1831018744 });
18311 if (values[i].tag() == .unreachable_value) {
18745 if (values[i] == .none) {
1831218746 const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
1831318747 _ = try block.addBinOp(.store, field_ptr, try sema.resolveInst(operand));
1831418748 }
......@@ -18322,7 +18756,7 @@ fn zirArrayInitAnon(
1832218756 element_refs[i] = try sema.resolveInst(operand);
1832318757 }
1832418758
18325 return block.addAggregateInit(tuple_ty, element_refs);
18759 return block.addAggregateInit(tuple_ty.toType(), element_refs);
1832618760}
1832718761
1832818762fn addConstantMaybeRef(
......@@ -18337,8 +18771,8 @@ fn addConstantMaybeRef(
1833718771 var anon_decl = try block.startAnonDecl();
1833818772 defer anon_decl.deinit();
1833918773 const decl = try anon_decl.finish(
18340 try ty.copy(anon_decl.arena()),
18341 try val.copy(anon_decl.arena()),
18774 ty,
18775 val,
1834218776 0, // default alignment
1834318777 );
1834418778 return sema.analyzeDeclRef(decl);
......@@ -18350,11 +18784,13 @@ fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro
1835018784 const ty_src = inst_data.src();
1835118785 const field_src = inst_data.src();
1835218786 const aggregate_ty = try sema.resolveType(block, ty_src, extra.container_type);
18353 const field_name = try sema.resolveConstString(block, field_src, extra.field_name, "field name must be comptime-known");
18787 const field_name = try sema.resolveConstStringIntern(block, field_src, extra.field_name, "field name must be comptime-known");
1835418788 return sema.fieldType(block, aggregate_ty, field_name, field_src, ty_src);
1835518789}
1835618790
1835718791fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18792 const mod = sema.mod;
18793 const ip = &mod.intern_pool;
1835818794 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1835918795 const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data;
1836018796 const ty_src = inst_data.src();
......@@ -18367,7 +18803,8 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1836718803 error.GenericPoison => return Air.Inst.Ref.generic_poison_type,
1836818804 else => |e| return e,
1836918805 };
18370 const field_name = sema.code.nullTerminatedString(extra.name_start);
18806 const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
18807 const field_name = try ip.getOrPutString(sema.gpa, zir_field_name);
1837118808 return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
1837218809}
1837318810
......@@ -18375,41 +18812,43 @@ fn fieldType(
1837518812 sema: *Sema,
1837618813 block: *Block,
1837718814 aggregate_ty: Type,
18378 field_name: []const u8,
18815 field_name: InternPool.NullTerminatedString,
1837918816 field_src: LazySrcLoc,
1838018817 ty_src: LazySrcLoc,
1838118818) CompileError!Air.Inst.Ref {
18819 const mod = sema.mod;
1838218820 var cur_ty = aggregate_ty;
1838318821 while (true) {
1838418822 const resolved_ty = try sema.resolveTypeFields(cur_ty);
1838518823 cur_ty = resolved_ty;
18386 switch (cur_ty.zigTypeTag()) {
18387 .Struct => {
18388 if (cur_ty.isAnonStruct()) {
18824 switch (cur_ty.zigTypeTag(mod)) {
18825 .Struct => switch (mod.intern_pool.indexToKey(cur_ty.toIntern())) {
18826 .anon_struct_type => |anon_struct| {
1838918827 const field_index = try sema.anonStructFieldIndex(block, cur_ty, field_name, field_src);
18390 return sema.addType(cur_ty.tupleFields().types[field_index]);
18391 }
18392 const struct_obj = cur_ty.castTag(.@"struct").?.data;
18393 const field = struct_obj.fields.get(field_name) orelse
18394 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18395 return sema.addType(field.ty);
18828 return sema.addType(anon_struct.types[field_index].toType());
18829 },
18830 .struct_type => |struct_type| {
18831 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
18832 const field = struct_obj.fields.get(field_name) orelse
18833 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
18834 return sema.addType(field.ty);
18835 },
18836 else => unreachable,
1839618837 },
1839718838 .Union => {
18398 const union_obj = cur_ty.cast(Type.Payload.Union).?.data;
18839 const union_obj = mod.typeToUnion(cur_ty).?;
1839918840 const field = union_obj.fields.get(field_name) orelse
1840018841 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
1840118842 return sema.addType(field.ty);
1840218843 },
1840318844 .Optional => {
18404 if (cur_ty.castTag(.optional)) |some| {
18405 // Struct/array init through optional requires the child type to not be a pointer.
18406 // If the child of .optional is a pointer it'll error on the next loop.
18407 cur_ty = some.data;
18408 continue;
18409 }
18845 // Struct/array init through optional requires the child type to not be a pointer.
18846 // If the child of .optional is a pointer it'll error on the next loop.
18847 cur_ty = mod.intern_pool.indexToKey(cur_ty.toIntern()).opt_type.toType();
18848 continue;
1841018849 },
1841118850 .ErrorUnion => {
18412 cur_ty = cur_ty.errorUnionPayload();
18851 cur_ty = cur_ty.errorUnionPayload(mod);
1841318852 continue;
1841418853 },
1841518854 else => {},
......@@ -18425,18 +18864,23 @@ fn zirErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
1842518864}
1842618865
1842718866fn getErrorReturnTrace(sema: *Sema, block: *Block) CompileError!Air.Inst.Ref {
18867 const mod = sema.mod;
1842818868 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
1842918869 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
18430 const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty);
18870 const ptr_stack_trace_ty = try mod.singleMutPtrType(stack_trace_ty);
18871 const opt_ptr_stack_trace_ty = try Type.optional(sema.arena, ptr_stack_trace_ty, mod);
1843118872
1843218873 if (sema.owner_func != null and
1843318874 sema.owner_func.?.calls_or_awaits_errorable_fn and
18434 sema.mod.comp.bin_file.options.error_return_tracing and
18435 sema.mod.backendSupportsFeature(.error_return_trace))
18875 mod.comp.bin_file.options.error_return_tracing and
18876 mod.backendSupportsFeature(.error_return_trace))
1843618877 {
1843718878 return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty);
1843818879 }
18439 return sema.addConstant(opt_ptr_stack_trace_ty, Value.null);
18880 return sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{
18881 .ty = opt_ptr_stack_trace_ty.toIntern(),
18882 .val = .none,
18883 } })).toValue());
1844018884}
1844118885
1844218886fn zirFrame(
......@@ -18449,27 +18893,28 @@ fn zirFrame(
1844918893}
1845018894
1845118895fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18896 const mod = sema.mod;
1845218897 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1845318898 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1845418899 const ty = try sema.resolveType(block, operand_src, inst_data.operand);
18455 if (ty.isNoReturn()) {
18900 if (ty.isNoReturn(mod)) {
1845618901 return sema.fail(block, operand_src, "no align available for type '{}'", .{ty.fmt(sema.mod)});
1845718902 }
18458 const target = sema.mod.getTarget();
18459 const val = try ty.lazyAbiAlignment(target, sema.arena);
18460 if (val.tag() == .lazy_align) {
18903 const val = try ty.lazyAbiAlignment(mod);
18904 if (val.isLazyAlign(mod)) {
1846118905 try sema.queueFullTypeResolution(ty);
1846218906 }
1846318907 return sema.addConstant(Type.comptime_int, val);
1846418908}
1846518909
1846618910fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
18911 const mod = sema.mod;
1846718912 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1846818913 const operand = try sema.resolveInst(inst_data.operand);
1846918914 if (try sema.resolveMaybeUndefVal(operand)) |val| {
18470 if (val.isUndef()) return sema.addConstUndef(Type.u1);
18471 if (val.toBool()) return sema.addConstant(Type.u1, Value.one);
18472 return sema.addConstant(Type.u1, Value.zero);
18915 if (val.isUndef(mod)) return sema.addConstUndef(Type.u1);
18916 if (val.toBool()) return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 1));
18917 return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
1847318918 }
1847418919 return block.addUnOp(.bool_to_int, operand);
1847518920}
......@@ -18480,8 +18925,8 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1848018925 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1848118926
1848218927 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
18483 const bytes = val.castTag(.@"error").?.data.name;
18484 return sema.addStrLit(block, bytes);
18928 const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name;
18929 return sema.addStrLit(block, sema.mod.intern_pool.stringToSlice(err_name));
1848518930 }
1848618931
1848718932 // Similar to zirTagName, we have special AIR instruction for the error name in case an optimimzation pass
......@@ -18499,16 +18944,17 @@ fn zirUnaryMath(
1849918944 const tracy = trace(@src());
1850018945 defer tracy.end();
1850118946
18947 const mod = sema.mod;
1850218948 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1850318949 const operand = try sema.resolveInst(inst_data.operand);
1850418950 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1850518951 const operand_ty = sema.typeOf(operand);
1850618952
18507 switch (operand_ty.zigTypeTag()) {
18953 switch (operand_ty.zigTypeTag(mod)) {
1850818954 .ComptimeFloat, .Float => {},
1850918955 .Vector => {
18510 const scalar_ty = operand_ty.scalarType();
18511 switch (scalar_ty.zigTypeTag()) {
18956 const scalar_ty = operand_ty.scalarType(mod);
18957 switch (scalar_ty.zigTypeTag(mod)) {
1851218958 .ComptimeFloat, .Float => {},
1851318959 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{scalar_ty.fmt(sema.mod)}),
1851418960 }
......@@ -18516,25 +18962,27 @@ fn zirUnaryMath(
1851618962 else => return sema.fail(block, operand_src, "expected vector of floats or float type, found '{}'", .{operand_ty.fmt(sema.mod)}),
1851718963 }
1851818964
18519 switch (operand_ty.zigTypeTag()) {
18965 switch (operand_ty.zigTypeTag(mod)) {
1852018966 .Vector => {
18521 const scalar_ty = operand_ty.scalarType();
18522 const vec_len = operand_ty.vectorLen();
18523 const result_ty = try Type.vector(sema.arena, vec_len, scalar_ty);
18967 const scalar_ty = operand_ty.scalarType(mod);
18968 const vec_len = operand_ty.vectorLen(mod);
18969 const result_ty = try mod.vectorType(.{
18970 .len = vec_len,
18971 .child = scalar_ty.toIntern(),
18972 });
1852418973 if (try sema.resolveMaybeUndefVal(operand)) |val| {
18525 if (val.isUndef())
18974 if (val.isUndef(mod))
1852618975 return sema.addConstUndef(result_ty);
1852718976
18528 var elem_buf: Value.ElemValueBuffer = undefined;
18529 const elems = try sema.arena.alloc(Value, vec_len);
18977 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
1853018978 for (elems, 0..) |*elem, i| {
18531 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);
18532 elem.* = try eval(elem_val, scalar_ty, sema.arena, sema.mod);
18979 const elem_val = try val.elemValue(sema.mod, i);
18980 elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod);
1853318981 }
18534 return sema.addConstant(
18535 result_ty,
18536 try Value.Tag.aggregate.create(sema.arena, elems),
18537 );
18982 return sema.addConstant(result_ty, (try mod.intern(.{ .aggregate = .{
18983 .ty = result_ty.toIntern(),
18984 .storage = .{ .elems = elems },
18985 } })).toValue());
1853818986 }
1853918987
1854018988 try sema.requireRuntimeBlock(block, operand_src, null);
......@@ -18542,7 +18990,7 @@ fn zirUnaryMath(
1854218990 },
1854318991 .ComptimeFloat, .Float => {
1854418992 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
18545 if (operand_val.isUndef())
18993 if (operand_val.isUndef(mod))
1854618994 return sema.addConstUndef(operand_ty);
1854718995 const result_val = try eval(operand_val, operand_ty, sema.arena, sema.mod);
1854818996 return sema.addConstant(operand_ty, result_val);
......@@ -18562,16 +19010,17 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1856219010 const operand = try sema.resolveInst(inst_data.operand);
1856319011 const operand_ty = sema.typeOf(operand);
1856419012 const mod = sema.mod;
19013 const ip = &mod.intern_pool;
1856519014
1856619015 try sema.resolveTypeLayout(operand_ty);
18567 const enum_ty = switch (operand_ty.zigTypeTag()) {
19016 const enum_ty = switch (operand_ty.zigTypeTag(mod)) {
1856819017 .EnumLiteral => {
1856919018 const val = try sema.resolveConstValue(block, .unneeded, operand, "");
18570 const bytes = val.castTag(.enum_literal).?.data;
18571 return sema.addStrLit(block, bytes);
19019 const tag_name = ip.indexToKey(val.toIntern()).enum_literal;
19020 return sema.addStrLit(block, ip.stringToSlice(tag_name));
1857219021 },
1857319022 .Enum => operand_ty,
18574 .Union => operand_ty.unionTagType() orelse {
19023 .Union => operand_ty.unionTagType(mod) orelse {
1857519024 const msg = msg: {
1857619025 const msg = try sema.errMsg(block, src, "union '{}' is untagged", .{
1857719026 operand_ty.fmt(sema.mod),
......@@ -18586,30 +19035,31 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1858619035 operand_ty.fmt(mod),
1858719036 }),
1858819037 };
18589 if (enum_ty.enumFieldCount() == 0) {
19038 if (enum_ty.enumFieldCount(mod) == 0) {
1859019039 // TODO I don't think this is the correct way to handle this but
1859119040 // it prevents a crash.
1859219041 return sema.fail(block, operand_src, "cannot get @tagName of empty enum '{}'", .{
1859319042 enum_ty.fmt(mod),
1859419043 });
1859519044 }
18596 const enum_decl_index = enum_ty.getOwnerDecl();
19045 const enum_decl_index = enum_ty.getOwnerDecl(mod);
1859719046 const casted_operand = try sema.coerce(block, enum_ty, operand, operand_src);
1859819047 if (try sema.resolveDefinedValue(block, operand_src, casted_operand)) |val| {
1859919048 const field_index = enum_ty.enumTagFieldIndex(val, mod) orelse {
1860019049 const enum_decl = mod.declPtr(enum_decl_index);
1860119050 const msg = msg: {
18602 const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{s}'", .{
18603 val.fmtValue(enum_ty, sema.mod), enum_decl.name,
19051 const msg = try sema.errMsg(block, src, "no field with value '{}' in enum '{}'", .{
19052 val.fmtValue(enum_ty, sema.mod), enum_decl.name.fmt(ip),
1860419053 });
1860519054 errdefer msg.destroy(sema.gpa);
18606 try mod.errNoteNonLazy(enum_decl.srcLoc(), msg, "declared here", .{});
19055 try mod.errNoteNonLazy(enum_decl.srcLoc(mod), msg, "declared here", .{});
1860719056 break :msg msg;
1860819057 };
1860919058 return sema.failWithOwnedErrorMsg(msg);
1861019059 };
18611 const field_name = enum_ty.enumFieldName(field_index);
18612 return sema.addStrLit(block, field_name);
19060 // TODO: write something like getCoercedInts to avoid needing to dupe
19061 const field_name = enum_ty.enumFieldName(field_index, mod);
19062 return sema.addStrLit(block, ip.stringToSlice(field_name));
1861319063 }
1861419064 try sema.requireRuntimeBlock(block, src, operand_src);
1861519065 if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) {
......@@ -18622,8 +19072,15 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1862219072 return block.addUnOp(.tag_name, casted_operand);
1862319073}
1862419074
18625fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
19075fn zirReify(
19076 sema: *Sema,
19077 block: *Block,
19078 extended: Zir.Inst.Extended.InstData,
19079 inst: Zir.Inst.Index,
19080) CompileError!Air.Inst.Ref {
1862619081 const mod = sema.mod;
19082 const gpa = sema.gpa;
19083 const ip = &mod.intern_pool;
1862719084 const name_strategy = @intToEnum(Zir.Inst.NameStrategy, extended.small);
1862819085 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
1862919086 const src = LazySrcLoc.nodeOffset(extra.node);
......@@ -18632,10 +19089,10 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1863219089 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
1863319090 const type_info = try sema.coerce(block, type_info_ty, uncasted_operand, operand_src);
1863419091 const val = try sema.resolveConstValue(block, operand_src, type_info, "operand to @Type must be comptime-known");
18635 const union_val = val.cast(Value.Payload.Union).?.data;
19092 const union_val = ip.indexToKey(val.toIntern()).un;
1863619093 const target = mod.getTarget();
18637 const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag, mod).?;
18638 if (union_val.val.anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
19094 if (try union_val.val.toValue().anyUndef(mod)) return sema.failWithUseOfUndef(block, src);
19095 const tag_index = type_info_ty.unionTagFieldIndex(union_val.tag.toValue(), mod).?;
1863919096 switch (@intToEnum(std.builtin.TypeId, tag_index)) {
1864019097 .Type => return Air.Inst.Ref.type_type,
1864119098 .Void => return Air.Inst.Ref.void_type,
......@@ -18648,41 +19105,48 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1864819105 .AnyFrame => return sema.failWithUseOfAsync(block, src),
1864919106 .EnumLiteral => return Air.Inst.Ref.enum_literal_type,
1865019107 .Int => {
18651 const struct_val = union_val.val.castTag(.aggregate).?.data;
18652 // TODO use reflection instead of magic numbers here
18653 const signedness_val = struct_val[0];
18654 const bits_val = struct_val[1];
18655
18656 const signedness = signedness_val.toEnum(std.builtin.Signedness);
18657 const bits = @intCast(u16, bits_val.toUnsignedInt(target));
18658 const ty = switch (signedness) {
18659 .signed => try Type.Tag.int_signed.create(sema.arena, bits),
18660 .unsigned => try Type.Tag.int_unsigned.create(sema.arena, bits),
18661 };
19108 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19109 const signedness_val = try union_val.val.toValue().fieldValue(
19110 mod,
19111 fields.getIndex(try ip.getOrPutString(gpa, "signedness")).?,
19112 );
19113 const bits_val = try union_val.val.toValue().fieldValue(
19114 mod,
19115 fields.getIndex(try ip.getOrPutString(gpa, "bits")).?,
19116 );
19117
19118 const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);
19119 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
19120 const ty = try mod.intType(signedness, bits);
1866219121 return sema.addType(ty);
1866319122 },
1866419123 .Vector => {
18665 const struct_val = union_val.val.castTag(.aggregate).?.data;
18666 // TODO use reflection instead of magic numbers here
18667 const len_val = struct_val[0];
18668 const child_val = struct_val[1];
19124 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19125 const len_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19126 try ip.getOrPutString(gpa, "len"),
19127 ).?);
19128 const child_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19129 try ip.getOrPutString(gpa, "child"),
19130 ).?);
1866919131
18670 const len = len_val.toUnsignedInt(target);
18671 var buffer: Value.ToTypeBuffer = undefined;
18672 const child_ty = child_val.toType(&buffer);
19132 const len = @intCast(u32, len_val.toUnsignedInt(mod));
19133 const child_ty = child_val.toType();
1867319134
1867419135 try sema.checkVectorElemType(block, src, child_ty);
1867519136
18676 const ty = try Type.vector(sema.arena, len, try child_ty.copy(sema.arena));
19137 const ty = try mod.vectorType(.{
19138 .len = len,
19139 .child = child_ty.toIntern(),
19140 });
1867719141 return sema.addType(ty);
1867819142 },
1867919143 .Float => {
18680 const struct_val = union_val.val.castTag(.aggregate).?.data;
18681 // TODO use reflection instead of magic numbers here
18682 // bits: comptime_int,
18683 const bits_val = struct_val[0];
19144 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19145 const bits_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19146 try ip.getOrPutString(gpa, "bits"),
19147 ).?);
1868419148
18685 const bits = @intCast(u16, bits_val.toUnsignedInt(target));
19149 const bits = @intCast(u16, bits_val.toUnsignedInt(mod));
1868619150 const ty = switch (bits) {
1868719151 16 => Type.f16,
1868819152 32 => Type.f32,
......@@ -18694,25 +19158,42 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1869419158 return sema.addType(ty);
1869519159 },
1869619160 .Pointer => {
18697 const struct_val = union_val.val.castTag(.aggregate).?.data;
18698 // TODO use reflection instead of magic numbers here
18699 const size_val = struct_val[0];
18700 const is_const_val = struct_val[1];
18701 const is_volatile_val = struct_val[2];
18702 const alignment_val = struct_val[3];
18703 const address_space_val = struct_val[4];
18704 const child_val = struct_val[5];
18705 const is_allowzero_val = struct_val[6];
18706 const sentinel_val = struct_val[7];
19161 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19162 const size_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19163 try ip.getOrPutString(gpa, "size"),
19164 ).?);
19165 const is_const_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19166 try ip.getOrPutString(gpa, "is_const"),
19167 ).?);
19168 const is_volatile_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19169 try ip.getOrPutString(gpa, "is_volatile"),
19170 ).?);
19171 const alignment_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19172 try ip.getOrPutString(gpa, "alignment"),
19173 ).?);
19174 const address_space_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19175 try ip.getOrPutString(gpa, "address_space"),
19176 ).?);
19177 const child_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19178 try ip.getOrPutString(gpa, "child"),
19179 ).?);
19180 const is_allowzero_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19181 try ip.getOrPutString(gpa, "is_allowzero"),
19182 ).?);
19183 const sentinel_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19184 try ip.getOrPutString(gpa, "sentinel"),
19185 ).?);
1870719186
1870819187 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
1870919188 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
1871019189 }
18711 const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?);
1871219190
18713 var buffer: Value.ToTypeBuffer = undefined;
18714 const unresolved_elem_ty = child_val.toType(&buffer);
18715 const elem_ty = if (abi_align == 0)
19191 const abi_align = InternPool.Alignment.fromByteUnits(
19192 (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?,
19193 );
19194
19195 const unresolved_elem_ty = child_val.toType();
19196 const elem_ty = if (abi_align == .none)
1871619197 unresolved_elem_ty
1871719198 else t: {
1871819199 const elem_ty = try sema.resolveTypeFields(unresolved_elem_ty);
......@@ -18720,301 +19201,282 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1872019201 break :t elem_ty;
1872119202 };
1872219203
18723 const ptr_size = size_val.toEnum(std.builtin.Type.Pointer.Size);
19204 const ptr_size = mod.toEnum(std.builtin.Type.Pointer.Size, size_val);
1872419205
18725 var actual_sentinel: ?Value = null;
18726 if (!sentinel_val.isNull()) {
18727 if (ptr_size == .One or ptr_size == .C) {
18728 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
19206 const actual_sentinel: InternPool.Index = s: {
19207 if (!sentinel_val.isNull(mod)) {
19208 if (ptr_size == .One or ptr_size == .C) {
19209 return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{});
19210 }
19211 const sentinel_ptr_val = sentinel_val.optionalValue(mod).?;
19212 const ptr_ty = try Type.ptr(sema.arena, mod, .{
19213 .@"addrspace" = .generic,
19214 .pointee_type = elem_ty,
19215 });
19216 const sent_val = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
19217 break :s sent_val.toIntern();
1872919218 }
18730 const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data;
18731 const ptr_ty = try Type.ptr(sema.arena, mod, .{
18732 .@"addrspace" = .generic,
18733 .pointee_type = try elem_ty.copy(sema.arena),
18734 });
18735 actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?;
18736 }
19219 break :s .none;
19220 };
1873719221
18738 if (elem_ty.zigTypeTag() == .NoReturn) {
19222 if (elem_ty.zigTypeTag(mod) == .NoReturn) {
1873919223 return sema.fail(block, src, "pointer to noreturn not allowed", .{});
18740 } else if (elem_ty.zigTypeTag() == .Fn) {
19224 } else if (elem_ty.zigTypeTag(mod) == .Fn) {
1874119225 if (ptr_size != .One) {
1874219226 return sema.fail(block, src, "function pointers must be single pointers", .{});
1874319227 }
18744 const fn_align = elem_ty.fnInfo().alignment;
18745 if (abi_align != 0 and fn_align != 0 and
19228 const fn_align = mod.typeToFunc(elem_ty).?.alignment;
19229 if (abi_align != .none and fn_align != .none and
1874619230 abi_align != fn_align)
1874719231 {
1874819232 return sema.fail(block, src, "function pointer alignment disagrees with function alignment", .{});
1874919233 }
18750 } else if (ptr_size == .Many and elem_ty.zigTypeTag() == .Opaque) {
19234 } else if (ptr_size == .Many and elem_ty.zigTypeTag(mod) == .Opaque) {
1875119235 return sema.fail(block, src, "unknown-length pointer to opaque not allowed", .{});
1875219236 } else if (ptr_size == .C) {
1875319237 if (!try sema.validateExternType(elem_ty, .other)) {
1875419238 const msg = msg: {
18755 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(sema.mod)});
18756 errdefer msg.destroy(sema.gpa);
19239 const msg = try sema.errMsg(block, src, "C pointers cannot point to non-C-ABI-compatible type '{}'", .{elem_ty.fmt(mod)});
19240 errdefer msg.destroy(gpa);
1875719241
18758 const src_decl = sema.mod.declPtr(block.src_decl);
18759 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), elem_ty, .other);
19242 const src_decl = mod.declPtr(block.src_decl);
19243 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), elem_ty, .other);
1876019244
1876119245 try sema.addDeclaredHereNote(msg, elem_ty);
1876219246 break :msg msg;
1876319247 };
1876419248 return sema.failWithOwnedErrorMsg(msg);
1876519249 }
18766 if (elem_ty.zigTypeTag() == .Opaque) {
19250 if (elem_ty.zigTypeTag(mod) == .Opaque) {
1876719251 return sema.fail(block, src, "C pointers cannot point to opaque types", .{});
1876819252 }
1876919253 }
1877019254
18771 const ty = try Type.ptr(sema.arena, mod, .{
18772 .size = ptr_size,
18773 .mutable = !is_const_val.toBool(),
18774 .@"volatile" = is_volatile_val.toBool(),
18775 .@"align" = abi_align,
18776 .@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace),
18777 .pointee_type = try elem_ty.copy(sema.arena),
18778 .@"allowzero" = is_allowzero_val.toBool(),
19255 const ty = try mod.ptrType(.{
19256 .child = elem_ty.toIntern(),
1877919257 .sentinel = actual_sentinel,
19258 .flags = .{
19259 .size = ptr_size,
19260 .is_const = is_const_val.toBool(),
19261 .is_volatile = is_volatile_val.toBool(),
19262 .alignment = abi_align,
19263 .address_space = mod.toEnum(std.builtin.AddressSpace, address_space_val),
19264 .is_allowzero = is_allowzero_val.toBool(),
19265 },
1878019266 });
1878119267 return sema.addType(ty);
1878219268 },
1878319269 .Array => {
18784 const struct_val = union_val.val.castTag(.aggregate).?.data;
18785 // TODO use reflection instead of magic numbers here
18786 // len: comptime_int,
18787 const len_val = struct_val[0];
18788 // child: type,
18789 const child_val = struct_val[1];
18790 // sentinel: ?*const anyopaque,
18791 const sentinel_val = struct_val[2];
18792
18793 const len = len_val.toUnsignedInt(target);
18794 var buffer: Value.ToTypeBuffer = undefined;
18795 const child_ty = try child_val.toType(&buffer).copy(sema.arena);
18796 const sentinel = if (sentinel_val.castTag(.opt_payload)) |p| blk: {
19270 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19271 const len_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19272 try ip.getOrPutString(gpa, "len"),
19273 ).?);
19274 const child_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19275 try ip.getOrPutString(gpa, "child"),
19276 ).?);
19277 const sentinel_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19278 try ip.getOrPutString(gpa, "sentinel"),
19279 ).?);
19280
19281 const len = len_val.toUnsignedInt(mod);
19282 const child_ty = child_val.toType();
19283 const sentinel = if (sentinel_val.optionalValue(mod)) |p| blk: {
1879719284 const ptr_ty = try Type.ptr(sema.arena, mod, .{
1879819285 .@"addrspace" = .generic,
1879919286 .pointee_type = child_ty,
1880019287 });
18801 break :blk (try sema.pointerDeref(block, src, p.data, ptr_ty)).?;
19288 break :blk (try sema.pointerDeref(block, src, p, ptr_ty)).?;
1880219289 } else null;
1880319290
18804 const ty = try Type.array(sema.arena, len, sentinel, child_ty, sema.mod);
19291 const ty = try Type.array(sema.arena, len, sentinel, child_ty, mod);
1880519292 return sema.addType(ty);
1880619293 },
1880719294 .Optional => {
18808 const struct_val = union_val.val.castTag(.aggregate).?.data;
18809 // TODO use reflection instead of magic numbers here
18810 // child: type,
18811 const child_val = struct_val[0];
19295 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19296 const child_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19297 try ip.getOrPutString(gpa, "child"),
19298 ).?);
1881219299
18813 var buffer: Value.ToTypeBuffer = undefined;
18814 const child_ty = try child_val.toType(&buffer).copy(sema.arena);
19300 const child_ty = child_val.toType();
1881519301
18816 const ty = try Type.optional(sema.arena, child_ty);
19302 const ty = try Type.optional(sema.arena, child_ty, mod);
1881719303 return sema.addType(ty);
1881819304 },
1881919305 .ErrorUnion => {
18820 const struct_val = union_val.val.castTag(.aggregate).?.data;
18821 // TODO use reflection instead of magic numbers here
18822 // error_set: type,
18823 const error_set_val = struct_val[0];
18824 // payload: type,
18825 const payload_val = struct_val[1];
18826
18827 var buffer: Value.ToTypeBuffer = undefined;
18828 const error_set_ty = try error_set_val.toType(&buffer).copy(sema.arena);
18829 const payload_ty = try payload_val.toType(&buffer).copy(sema.arena);
18830
18831 if (error_set_ty.zigTypeTag() != .ErrorSet) {
19306 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19307 const error_set_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19308 try ip.getOrPutString(gpa, "error_set"),
19309 ).?);
19310 const payload_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19311 try ip.getOrPutString(gpa, "payload"),
19312 ).?);
19313
19314 const error_set_ty = error_set_val.toType();
19315 const payload_ty = payload_val.toType();
19316
19317 if (error_set_ty.zigTypeTag(mod) != .ErrorSet) {
1883219318 return sema.fail(block, src, "Type.ErrorUnion.error_set must be an error set type", .{});
1883319319 }
1883419320
18835 const ty = try Type.Tag.error_union.create(sema.arena, .{
18836 .error_set = error_set_ty,
18837 .payload = payload_ty,
18838 });
19321 const ty = try mod.errorUnionType(error_set_ty, payload_ty);
1883919322 return sema.addType(ty);
1884019323 },
1884119324 .ErrorSet => {
18842 const payload_val = union_val.val.optionalValue() orelse
18843 return sema.addType(Type.initTag(.anyerror));
18844 const slice_val = payload_val.castTag(.slice).?.data;
19325 const payload_val = union_val.val.toValue().optionalValue(mod) orelse
19326 return sema.addType(Type.anyerror);
1884519327
18846 const len = try sema.usizeCast(block, src, slice_val.len.toUnsignedInt(mod.getTarget()));
18847 var names: Module.ErrorSet.NameMap = .{};
19328 const len = try sema.usizeCast(block, src, payload_val.sliceLen(mod));
19329 var names: Module.Fn.InferredErrorSet.NameMap = .{};
1884819330 try names.ensureUnusedCapacity(sema.arena, len);
18849 var i: usize = 0;
18850 while (i < len) : (i += 1) {
18851 var buf: Value.ElemValueBuffer = undefined;
18852 const elem_val = slice_val.ptr.elemValueBuffer(mod, i, &buf);
18853 const struct_val = elem_val.castTag(.aggregate).?.data;
18854 // TODO use reflection instead of magic numbers here
18855 // error_set: type,
18856 const name_val = struct_val[0];
18857 const name_str = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, sema.mod);
18858
18859 const kv = try mod.getErrorValue(name_str);
18860 const gop = names.getOrPutAssumeCapacity(kv.key);
19331 for (0..len) |i| {
19332 const elem_val = try payload_val.elemValue(mod, i);
19333 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19334 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19335 try ip.getOrPutString(gpa, "name"),
19336 ).?);
19337
19338 const name = try name_val.toIpString(Type.slice_const_u8, mod);
19339 _ = try mod.getErrorValue(name);
19340 const gop = names.getOrPutAssumeCapacity(name);
1886119341 if (gop.found_existing) {
18862 return sema.fail(block, src, "duplicate error '{s}'", .{name_str});
19342 return sema.fail(block, src, "duplicate error '{}'", .{
19343 name.fmt(ip),
19344 });
1886319345 }
1886419346 }
1886519347
18866 // names must be sorted
18867 Module.ErrorSet.sortNames(&names);
18868 const ty = try Type.Tag.error_set_merged.create(sema.arena, names);
19348 const ty = try mod.errorSetFromUnsortedNames(names.keys());
1886919349 return sema.addType(ty);
1887019350 },
1887119351 .Struct => {
18872 // TODO use reflection instead of magic numbers here
18873 const struct_val = union_val.val.castTag(.aggregate).?.data;
18874 // layout: containerlayout,
18875 const layout_val = struct_val[0];
18876 // backing_int: ?type,
18877 const backing_int_val = struct_val[1];
18878 // fields: []const enumfield,
18879 const fields_val = struct_val[2];
18880 // decls: []const declaration,
18881 const decls_val = struct_val[3];
18882 // is_tuple: bool,
18883 const is_tuple_val = struct_val[4];
18884 assert(struct_val.len == 5);
18885
18886 const layout = layout_val.toEnum(std.builtin.Type.ContainerLayout);
19352 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19353 const layout_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19354 try ip.getOrPutString(gpa, "layout"),
19355 ).?);
19356 const backing_integer_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19357 try ip.getOrPutString(gpa, "backing_integer"),
19358 ).?);
19359 const fields_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19360 try ip.getOrPutString(gpa, "fields"),
19361 ).?);
19362 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19363 try ip.getOrPutString(gpa, "decls"),
19364 ).?);
19365 const is_tuple_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19366 try ip.getOrPutString(gpa, "is_tuple"),
19367 ).?);
19368
19369 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
1888719370
1888819371 // Decls
1888919372 if (decls_val.sliceLen(mod) > 0) {
1889019373 return sema.fail(block, src, "reified structs must have no decls", .{});
1889119374 }
1889219375
18893 if (layout != .Packed and !backing_int_val.isNull()) {
19376 if (layout != .Packed and !backing_integer_val.isNull(mod)) {
1889419377 return sema.fail(block, src, "non-packed struct does not support backing integer type", .{});
1889519378 }
1889619379
18897 return try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy, is_tuple_val.toBool());
19380 return try sema.reifyStruct(block, inst, src, layout, backing_integer_val, fields_val, name_strategy, is_tuple_val.toBool());
1889819381 },
1889919382 .Enum => {
18900 const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data;
18901 // TODO use reflection instead of magic numbers here
18902 // tag_type: type,
18903 const tag_type_val = struct_val[0];
18904 // fields: []const EnumField,
18905 const fields_val = struct_val[1];
18906 // decls: []const Declaration,
18907 const decls_val = struct_val[2];
18908 // is_exhaustive: bool,
18909 const is_exhaustive_val = struct_val[3];
19383 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19384 const tag_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19385 try ip.getOrPutString(gpa, "tag_type"),
19386 ).?);
19387 const fields_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19388 try ip.getOrPutString(gpa, "fields"),
19389 ).?);
19390 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19391 try ip.getOrPutString(gpa, "decls"),
19392 ).?);
19393 const is_exhaustive_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19394 try ip.getOrPutString(gpa, "is_exhaustive"),
19395 ).?);
1891019396
1891119397 // Decls
1891219398 if (decls_val.sliceLen(mod) > 0) {
1891319399 return sema.fail(block, src, "reified enums must have no decls", .{});
1891419400 }
1891519401
18916 const gpa = sema.gpa;
18917 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
18918 errdefer new_decl_arena.deinit();
18919 const new_decl_arena_allocator = new_decl_arena.allocator();
19402 const int_tag_ty = tag_type_val.toType();
19403 if (int_tag_ty.zigTypeTag(mod) != .Int) {
19404 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
19405 }
19406
19407 // Because these things each reference each other, `undefined`
19408 // placeholders are used before being set after the enum type gains
19409 // an InternPool index.
1892019410
18921 // Define our empty enum decl
18922 const enum_obj = try new_decl_arena_allocator.create(Module.EnumFull);
18923 const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumFull);
18924 enum_ty_payload.* = .{
18925 .base = .{
18926 .tag = if (!is_exhaustive_val.toBool())
18927 .enum_nonexhaustive
18928 else
18929 .enum_full,
18930 },
18931 .data = enum_obj,
18932 };
18933 const enum_ty = Type.initPayload(&enum_ty_payload.base);
18934 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
1893519411 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
18936 .ty = Type.type,
18937 .val = enum_val,
19412 .ty = Type.noreturn,
19413 .val = Value.@"unreachable",
1893819414 }, name_strategy, "enum", inst);
1893919415 const new_decl = mod.declPtr(new_decl_index);
1894019416 new_decl.owns_tv = true;
18941 errdefer mod.abortAnonDecl(new_decl_index);
19417 errdefer {
19418 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19419 mod.abortAnonDecl(new_decl_index);
19420 }
1894219421
18943 enum_obj.* = .{
18944 .owner_decl = new_decl_index,
18945 .tag_ty = Type.null,
18946 .tag_ty_inferred = false,
18947 .fields = .{},
18948 .values = .{},
18949 .namespace = .{
18950 .parent = block.namespace,
18951 .ty = enum_ty,
18952 .file_scope = block.getFileScope(),
18953 },
18954 };
19422 // Define our empty enum decl
19423 const fields_len = @intCast(u32, try sema.usizeCast(block, src, fields_val.sliceLen(mod)));
19424 const incomplete_enum = try ip.getIncompleteEnum(gpa, .{
19425 .decl = new_decl_index,
19426 .namespace = .none,
19427 .fields_len = fields_len,
19428 .has_values = true,
19429 .tag_mode = if (!is_exhaustive_val.toBool())
19430 .nonexhaustive
19431 else
19432 .explicit,
19433 .tag_ty = int_tag_ty.toIntern(),
19434 });
19435 // TODO: figure out InternPool removals for incremental compilation
19436 //errdefer ip.remove(incomplete_enum.index);
1895519437
18956 // Enum tag type
18957 var buffer: Value.ToTypeBuffer = undefined;
18958 const int_tag_ty = try tag_type_val.toType(&buffer).copy(new_decl_arena_allocator);
19438 new_decl.ty = Type.type;
19439 new_decl.val = incomplete_enum.index.toValue();
1895919440
18960 if (int_tag_ty.zigTypeTag() != .Int) {
18961 return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
18962 }
18963 enum_obj.tag_ty = int_tag_ty;
18964
18965 // Fields
18966 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
18967 try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
18968 try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{
18969 .ty = enum_obj.tag_ty,
18970 .mod = mod,
18971 });
19441 for (0..fields_len) |field_i| {
19442 const elem_val = try fields_val.elemValue(mod, field_i);
19443 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19444 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19445 try ip.getOrPutString(gpa, "name"),
19446 ).?);
19447 const value_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19448 try ip.getOrPutString(gpa, "value"),
19449 ).?);
1897219450
18973 var field_i: usize = 0;
18974 while (field_i < fields_len) : (field_i += 1) {
18975 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, field_i);
18976 const field_struct_val: []const Value = elem_val.castTag(.aggregate).?.data;
18977 // TODO use reflection instead of magic numbers here
18978 // name: []const u8
18979 const name_val = field_struct_val[0];
18980 // value: comptime_int
18981 const value_val = field_struct_val[1];
18982
18983 const field_name = try name_val.toAllocatedBytes(
18984 Type.initTag(.const_slice_u8),
18985 new_decl_arena_allocator,
18986 sema.mod,
18987 );
19451 const field_name = try name_val.toIpString(Type.slice_const_u8, mod);
1898819452
18989 if (!try sema.intFitsInType(value_val, enum_obj.tag_ty, null)) {
19453 if (!try sema.intFitsInType(value_val, int_tag_ty, null)) {
1899019454 // TODO: better source location
18991 return sema.fail(block, src, "field '{s}' with enumeration value '{}' is too large for backing int type '{}'", .{
18992 field_name,
19455 return sema.fail(block, src, "field '{}' with enumeration value '{}' is too large for backing int type '{}'", .{
19456 field_name.fmt(ip),
1899319457 value_val.fmtValue(Type.comptime_int, mod),
18994 enum_obj.tag_ty.fmt(mod),
19458 int_tag_ty.fmt(mod),
1899519459 });
1899619460 }
1899719461
18998 const gop_field = enum_obj.fields.getOrPutAssumeCapacity(field_name);
18999 if (gop_field.found_existing) {
19462 if (try incomplete_enum.addFieldName(ip, gpa, field_name)) |other_index| {
1900019463 const msg = msg: {
19001 const msg = try sema.errMsg(block, src, "duplicate enum field '{s}'", .{field_name});
19464 const msg = try sema.errMsg(block, src, "duplicate enum field '{}'", .{
19465 field_name.fmt(ip),
19466 });
1900219467 errdefer msg.destroy(gpa);
19468 _ = other_index; // TODO: this note is incorrect
1900319469 try sema.errNote(block, src, msg, "other field here", .{});
1900419470 break :msg msg;
1900519471 };
1900619472 return sema.failWithOwnedErrorMsg(msg);
1900719473 }
1900819474
19009 const copied_tag_val = try value_val.copy(new_decl_arena_allocator);
19010 const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
19011 .ty = enum_obj.tag_ty,
19012 .mod = mod,
19013 });
19014 if (gop_val.found_existing) {
19475 if (try incomplete_enum.addFieldValue(ip, gpa, (try mod.getCoerced(value_val, int_tag_ty)).toIntern())) |other| {
1901519476 const msg = msg: {
1901619477 const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{value_val.fmtValue(Type.comptime_int, mod)});
1901719478 errdefer msg.destroy(gpa);
19479 _ = other; // TODO: this note is incorrect
1901819480 try sema.errNote(block, src, msg, "other enum tag value here", .{});
1901919481 break :msg msg;
1902019482 };
......@@ -19022,182 +19484,209 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1902219484 }
1902319485 }
1902419486
19025 try new_decl.finalizeNewArena(&new_decl_arena);
19026 return sema.analyzeDeclVal(block, src, new_decl_index);
19487 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19488 try mod.finalizeAnonDecl(new_decl_index);
19489 return decl_val;
1902719490 },
1902819491 .Opaque => {
19029 const struct_val = union_val.val.castTag(.aggregate).?.data;
19030 // decls: []const Declaration,
19031 const decls_val = struct_val[0];
19492 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19493 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19494 try ip.getOrPutString(gpa, "decls"),
19495 ).?);
1903219496
1903319497 // Decls
1903419498 if (decls_val.sliceLen(mod) > 0) {
1903519499 return sema.fail(block, src, "reified opaque must have no decls", .{});
1903619500 }
1903719501
19038 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
19039 errdefer new_decl_arena.deinit();
19040 const new_decl_arena_allocator = new_decl_arena.allocator();
19502 // Because these three things each reference each other,
19503 // `undefined` placeholders are used in two places before being set
19504 // after the opaque type gains an InternPool index.
1904119505
19042 const opaque_obj = try new_decl_arena_allocator.create(Module.Opaque);
19043 const opaque_ty_payload = try new_decl_arena_allocator.create(Type.Payload.Opaque);
19044 opaque_ty_payload.* = .{
19045 .base = .{ .tag = .@"opaque" },
19046 .data = opaque_obj,
19047 };
19048 const opaque_ty = Type.initPayload(&opaque_ty_payload.base);
19049 const opaque_val = try Value.Tag.ty.create(new_decl_arena_allocator, opaque_ty);
1905019506 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19051 .ty = Type.type,
19052 .val = opaque_val,
19507 .ty = Type.noreturn,
19508 .val = Value.@"unreachable",
1905319509 }, name_strategy, "opaque", inst);
1905419510 const new_decl = mod.declPtr(new_decl_index);
1905519511 new_decl.owns_tv = true;
19056 errdefer mod.abortAnonDecl(new_decl_index);
19512 errdefer {
19513 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19514 mod.abortAnonDecl(new_decl_index);
19515 }
1905719516
19058 opaque_obj.* = .{
19059 .owner_decl = new_decl_index,
19060 .namespace = .{
19061 .parent = block.namespace,
19062 .ty = opaque_ty,
19063 .file_scope = block.getFileScope(),
19064 },
19065 };
19517 const new_namespace_index = try mod.createNamespace(.{
19518 .parent = block.namespace.toOptional(),
19519 .ty = undefined,
19520 .file_scope = block.getFileScope(mod),
19521 });
19522 const new_namespace = mod.namespacePtr(new_namespace_index);
19523 errdefer mod.destroyNamespace(new_namespace_index);
1906619524
19067 try new_decl.finalizeNewArena(&new_decl_arena);
19068 return sema.analyzeDeclVal(block, src, new_decl_index);
19525 const opaque_ty = try mod.intern(.{ .opaque_type = .{
19526 .decl = new_decl_index,
19527 .namespace = new_namespace_index,
19528 } });
19529 // TODO: figure out InternPool removals for incremental compilation
19530 //errdefer ip.remove(opaque_ty);
19531
19532 new_decl.ty = Type.type;
19533 new_decl.val = opaque_ty.toValue();
19534 new_namespace.ty = opaque_ty.toType();
19535
19536 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19537 try mod.finalizeAnonDecl(new_decl_index);
19538 return decl_val;
1906919539 },
1907019540 .Union => {
19071 // TODO use reflection instead of magic numbers here
19072 const struct_val = union_val.val.castTag(.aggregate).?.data;
19073 // layout: containerlayout,
19074 const layout_val = struct_val[0];
19075 // tag_type: ?type,
19076 const tag_type_val = struct_val[1];
19077 // fields: []const enumfield,
19078 const fields_val = struct_val[2];
19079 // decls: []const declaration,
19080 const decls_val = struct_val[3];
19541 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19542 const layout_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19543 try ip.getOrPutString(gpa, "layout"),
19544 ).?);
19545 const tag_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19546 try ip.getOrPutString(gpa, "tag_type"),
19547 ).?);
19548 const fields_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19549 try ip.getOrPutString(gpa, "fields"),
19550 ).?);
19551 const decls_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19552 try ip.getOrPutString(gpa, "decls"),
19553 ).?);
1908119554
1908219555 // Decls
1908319556 if (decls_val.sliceLen(mod) > 0) {
1908419557 return sema.fail(block, src, "reified unions must have no decls", .{});
1908519558 }
19086 const layout = layout_val.toEnum(std.builtin.Type.ContainerLayout);
19559 const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
1908719560
19088 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
19089 errdefer new_decl_arena.deinit();
19090 const new_decl_arena_allocator = new_decl_arena.allocator();
19561 // Because these three things each reference each other, `undefined`
19562 // placeholders are used before being set after the union type gains an
19563 // InternPool index.
1909119564
19092 const union_obj = try new_decl_arena_allocator.create(Module.Union);
19093 const type_tag = if (!tag_type_val.isNull())
19094 Type.Tag.union_tagged
19095 else if (layout != .Auto)
19096 Type.Tag.@"union"
19097 else switch (block.sema.mod.optimizeMode()) {
19098 .Debug, .ReleaseSafe => Type.Tag.union_safety_tagged,
19099 .ReleaseFast, .ReleaseSmall => Type.Tag.@"union",
19100 };
19101 const union_payload = try new_decl_arena_allocator.create(Type.Payload.Union);
19102 union_payload.* = .{
19103 .base = .{ .tag = type_tag },
19104 .data = union_obj,
19105 };
19106 const union_ty = Type.initPayload(&union_payload.base);
19107 const new_union_val = try Value.Tag.ty.create(new_decl_arena_allocator, union_ty);
1910819565 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19109 .ty = Type.type,
19110 .val = new_union_val,
19566 .ty = Type.noreturn,
19567 .val = Value.@"unreachable",
1911119568 }, name_strategy, "union", inst);
1911219569 const new_decl = mod.declPtr(new_decl_index);
1911319570 new_decl.owns_tv = true;
19114 errdefer mod.abortAnonDecl(new_decl_index);
19115 union_obj.* = .{
19571 errdefer {
19572 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19573 mod.abortAnonDecl(new_decl_index);
19574 }
19575
19576 const new_namespace_index = try mod.createNamespace(.{
19577 .parent = block.namespace.toOptional(),
19578 .ty = undefined,
19579 .file_scope = block.getFileScope(mod),
19580 });
19581 const new_namespace = mod.namespacePtr(new_namespace_index);
19582 errdefer mod.destroyNamespace(new_namespace_index);
19583
19584 const union_index = try mod.createUnion(.{
1911619585 .owner_decl = new_decl_index,
19117 .tag_ty = Type.initTag(.null),
19586 .tag_ty = Type.null,
1911819587 .fields = .{},
1911919588 .zir_index = inst,
1912019589 .layout = layout,
1912119590 .status = .have_field_types,
19122 .namespace = .{
19123 .parent = block.namespace,
19124 .ty = union_ty,
19125 .file_scope = block.getFileScope(),
19591 .namespace = new_namespace_index,
19592 });
19593 const union_obj = mod.unionPtr(union_index);
19594 errdefer mod.destroyUnion(union_index);
19595
19596 const union_ty = try ip.get(gpa, .{ .union_type = .{
19597 .index = union_index,
19598 .runtime_tag = if (!tag_type_val.isNull(mod))
19599 .tagged
19600 else if (layout != .Auto)
19601 .none
19602 else switch (mod.optimizeMode()) {
19603 .Debug, .ReleaseSafe => .safety,
19604 .ReleaseFast, .ReleaseSmall => .none,
1912619605 },
19127 };
19606 } });
19607 // TODO: figure out InternPool removals for incremental compilation
19608 //errdefer ip.remove(union_ty);
19609
19610 new_decl.ty = Type.type;
19611 new_decl.val = union_ty.toValue();
19612 new_namespace.ty = union_ty.toType();
1912819613
1912919614 // Tag type
19130 var tag_ty_field_names: ?Module.EnumFull.NameMap = null;
19131 var enum_field_names: ?*Module.EnumNumbered.NameMap = null;
1913219615 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
19133 if (tag_type_val.optionalValue()) |payload_val| {
19134 var buffer: Value.ToTypeBuffer = undefined;
19135 union_obj.tag_ty = try payload_val.toType(&buffer).copy(new_decl_arena_allocator);
19616 var explicit_tags_seen: []bool = &.{};
19617 var enum_field_names: []InternPool.NullTerminatedString = &.{};
19618 if (tag_type_val.optionalValue(mod)) |payload_val| {
19619 union_obj.tag_ty = payload_val.toType();
19620
19621 const enum_type = switch (ip.indexToKey(union_obj.tag_ty.toIntern())) {
19622 .enum_type => |x| x,
19623 else => return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{}),
19624 };
1913619625
19137 if (union_obj.tag_ty.zigTypeTag() != .Enum) {
19138 return sema.fail(block, src, "Type.Union.tag_type must be an enum type", .{});
19139 }
19140 tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena);
19626 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
19627 @memset(explicit_tags_seen, false);
1914119628 } else {
19142 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, fields_len, null);
19143 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
19629 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
1914419630 }
1914519631
1914619632 // Fields
19147 try union_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
19148
19149 var i: usize = 0;
19150 while (i < fields_len) : (i += 1) {
19151 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i);
19152 const field_struct_val = elem_val.castTag(.aggregate).?.data;
19153 // TODO use reflection instead of magic numbers here
19154 // name: []const u8
19155 const name_val = field_struct_val[0];
19156 // type: type,
19157 const type_val = field_struct_val[1];
19158 // alignment: comptime_int,
19159 const alignment_val = field_struct_val[2];
19160
19161 const field_name = try name_val.toAllocatedBytes(
19162 Type.initTag(.const_slice_u8),
19163 new_decl_arena_allocator,
19164 sema.mod,
19165 );
19166
19167 if (enum_field_names) |set| {
19168 set.putAssumeCapacity(field_name, {});
19169 }
19170
19171 if (tag_ty_field_names) |*names| {
19172 const enum_has_field = names.orderedRemove(field_name);
19173 if (!enum_has_field) {
19633 try union_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);
19634
19635 for (0..fields_len) |i| {
19636 const elem_val = try fields_val.elemValue(mod, i);
19637 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19638 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19639 try ip.getOrPutString(gpa, "name"),
19640 ).?);
19641 const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19642 try ip.getOrPutString(gpa, "type"),
19643 ).?);
19644 const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19645 try ip.getOrPutString(gpa, "alignment"),
19646 ).?);
19647
19648 const field_name = try name_val.toIpString(Type.slice_const_u8, mod);
19649
19650 if (enum_field_names.len != 0) {
19651 enum_field_names[i] = field_name;
19652 }
19653
19654 if (explicit_tags_seen.len > 0) {
19655 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
19656 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
1917419657 const msg = msg: {
19175 const msg = try sema.errMsg(block, src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });
19176 errdefer msg.destroy(sema.gpa);
19658 const msg = try sema.errMsg(block, src, "no field named '{}' in enum '{}'", .{
19659 field_name.fmt(ip),
19660 union_obj.tag_ty.fmt(mod),
19661 });
19662 errdefer msg.destroy(gpa);
1917719663 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
1917819664 break :msg msg;
1917919665 };
1918019666 return sema.failWithOwnedErrorMsg(msg);
19181 }
19667 };
19668 // No check for duplicate because the check already happened in order
19669 // to create the enum type in the first place.
19670 assert(!explicit_tags_seen[enum_index]);
19671 explicit_tags_seen[enum_index] = true;
1918219672 }
1918319673
1918419674 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
1918519675 if (gop.found_existing) {
1918619676 // TODO: better source location
19187 return sema.fail(block, src, "duplicate union field {s}", .{field_name});
19677 return sema.fail(block, src, "duplicate union field {}", .{field_name.fmt(ip)});
1918819678 }
1918919679
19190 var buffer: Value.ToTypeBuffer = undefined;
19191 const field_ty = try type_val.toType(&buffer).copy(new_decl_arena_allocator);
19680 const field_ty = type_val.toType();
1919219681 gop.value_ptr.* = .{
1919319682 .ty = field_ty,
19194 .abi_align = @intCast(u32, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?),
19683 .abi_align = @intCast(u32, (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?),
1919519684 };
1919619685
19197 if (field_ty.zigTypeTag() == .Opaque) {
19686 if (field_ty.zigTypeTag(mod) == .Opaque) {
1919819687 const msg = msg: {
1919919688 const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in unions", .{});
19200 errdefer msg.destroy(sema.gpa);
19689 errdefer msg.destroy(gpa);
1920119690
1920219691 try sema.addDeclaredHereNote(msg, field_ty);
1920319692 break :msg msg;
......@@ -19206,23 +19695,23 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1920619695 }
1920719696 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
1920819697 const msg = msg: {
19209 const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
19210 errdefer msg.destroy(sema.gpa);
19698 const msg = try sema.errMsg(block, src, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
19699 errdefer msg.destroy(gpa);
1921119700
19212 const src_decl = sema.mod.declPtr(block.src_decl);
19213 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), field_ty, .union_field);
19701 const src_decl = mod.declPtr(block.src_decl);
19702 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .union_field);
1921419703
1921519704 try sema.addDeclaredHereNote(msg, field_ty);
1921619705 break :msg msg;
1921719706 };
1921819707 return sema.failWithOwnedErrorMsg(msg);
19219 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
19708 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) {
1922019709 const msg = msg: {
19221 const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
19222 errdefer msg.destroy(sema.gpa);
19710 const msg = try sema.errMsg(block, src, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
19711 errdefer msg.destroy(gpa);
1922319712
19224 const src_decl = sema.mod.declPtr(block.src_decl);
19225 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl), field_ty);
19713 const src_decl = mod.declPtr(block.src_decl);
19714 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty);
1922619715
1922719716 try sema.addDeclaredHereNote(msg, field_ty);
1922819717 break :msg msg;
......@@ -19231,47 +19720,61 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1923119720 }
1923219721 }
1923319722
19234 if (tag_ty_field_names) |names| {
19235 if (names.count() > 0) {
19723 if (explicit_tags_seen.len > 0) {
19724 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
19725 if (tag_info.names.len > fields_len) {
1923619726 const msg = msg: {
1923719727 const msg = try sema.errMsg(block, src, "enum field(s) missing in union", .{});
19238 errdefer msg.destroy(sema.gpa);
19728 errdefer msg.destroy(gpa);
1923919729
1924019730 const enum_ty = union_obj.tag_ty;
19241 for (names.keys()) |field_name| {
19242 const field_index = enum_ty.enumFieldIndex(field_name).?;
19243 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
19731 for (tag_info.names, 0..) |field_name, field_index| {
19732 if (explicit_tags_seen[field_index]) continue;
19733 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
19734 field_name.fmt(ip),
19735 });
1924419736 }
1924519737 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
1924619738 break :msg msg;
1924719739 };
1924819740 return sema.failWithOwnedErrorMsg(msg);
1924919741 }
19742 } else {
19743 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, enum_field_names, null);
1925019744 }
1925119745
19252 try new_decl.finalizeNewArena(&new_decl_arena);
19253 return sema.analyzeDeclVal(block, src, new_decl_index);
19746 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
19747 try mod.finalizeAnonDecl(new_decl_index);
19748 return decl_val;
1925419749 },
1925519750 .Fn => {
19256 const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data;
19257 // TODO use reflection instead of magic numbers here
19258 // calling_convention: CallingConvention,
19259 const cc = struct_val[0].toEnum(std.builtin.CallingConvention);
19260 // alignment: comptime_int,
19261 const alignment_val = struct_val[1];
19262 // is_generic: bool,
19263 const is_generic = struct_val[2].toBool();
19264 // is_var_args: bool,
19265 const is_var_args = struct_val[3].toBool();
19266 // return_type: ?type,
19267 const return_type_val = struct_val[4];
19268 // args: []const Param,
19269 const args_val = struct_val[5];
19270
19751 const fields = ip.typeOf(union_val.val).toType().structFields(mod);
19752 const calling_convention_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19753 try ip.getOrPutString(gpa, "calling_convention"),
19754 ).?);
19755 const alignment_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19756 try ip.getOrPutString(gpa, "alignment"),
19757 ).?);
19758 const is_generic_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19759 try ip.getOrPutString(gpa, "is_generic"),
19760 ).?);
19761 const is_var_args_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19762 try ip.getOrPutString(gpa, "is_var_args"),
19763 ).?);
19764 const return_type_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19765 try ip.getOrPutString(gpa, "return_type"),
19766 ).?);
19767 const params_val = try union_val.val.toValue().fieldValue(mod, fields.getIndex(
19768 try ip.getOrPutString(gpa, "params"),
19769 ).?);
19770
19771 const is_generic = is_generic_val.toBool();
1927119772 if (is_generic) {
1927219773 return sema.fail(block, src, "Type.Fn.is_generic must be false for @Type", .{});
1927319774 }
1927419775
19776 const is_var_args = is_var_args_val.toBool();
19777 const cc = mod.toEnum(std.builtin.CallingConvention, calling_convention_val);
1927519778 if (is_var_args and cc != .C) {
1927619779 return sema.fail(block, src, "varargs functions must have C calling convention", .{});
1927719780 }
......@@ -19280,63 +19783,55 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1928019783 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
1928119784 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
1928219785 }
19283 const alignment = @intCast(u29, alignment_val.toUnsignedInt(target));
19786 const alignment = @intCast(u29, alignment_val.toUnsignedInt(mod));
1928419787 if (alignment == target_util.defaultFunctionAlignment(target)) {
19285 break :alignment 0;
19788 break :alignment .none;
1928619789 } else {
19287 break :alignment alignment;
19790 break :alignment InternPool.Alignment.fromByteUnits(alignment);
1928819791 }
1928919792 };
19290 const return_type = return_type_val.optionalValue() orelse
19793 const return_type = return_type_val.optionalValue(mod) orelse
1929119794 return sema.fail(block, src, "Type.Fn.return_type must be non-null for @Type", .{});
1929219795
19293 var buf: Value.ToTypeBuffer = undefined;
19294
19295 const args_slice_val = args_val.castTag(.slice).?.data;
19296 const args_len = try sema.usizeCast(block, src, args_slice_val.len.toUnsignedInt(mod.getTarget()));
19297
19298 const param_types = try sema.arena.alloc(Type, args_len);
19299 const comptime_params = try sema.arena.alloc(bool, args_len);
19796 const args_len = try sema.usizeCast(block, src, params_val.sliceLen(mod));
19797 const param_types = try sema.arena.alloc(InternPool.Index, args_len);
1930019798
1930119799 var noalias_bits: u32 = 0;
19302 var i: usize = 0;
19303 while (i < args_len) : (i += 1) {
19304 var arg_buf: Value.ElemValueBuffer = undefined;
19305 const arg = args_slice_val.ptr.elemValueBuffer(mod, i, &arg_buf);
19306 const arg_val = arg.castTag(.aggregate).?.data;
19307 // TODO use reflection instead of magic numbers here
19308 // is_generic: bool,
19309 const arg_is_generic = arg_val[0].toBool();
19310 // is_noalias: bool,
19311 const arg_is_noalias = arg_val[1].toBool();
19312 // type: ?type,
19313 const param_type_opt_val = arg_val[2];
19314
19315 if (arg_is_generic) {
19800 for (param_types, 0..) |*param_type, i| {
19801 const elem_val = try params_val.elemValue(mod, i);
19802 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19803 const param_is_generic_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19804 try ip.getOrPutString(gpa, "is_generic"),
19805 ).?);
19806 const param_is_noalias_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19807 try ip.getOrPutString(gpa, "is_noalias"),
19808 ).?);
19809 const opt_param_type_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19810 try ip.getOrPutString(gpa, "type"),
19811 ).?);
19812
19813 if (param_is_generic_val.toBool()) {
1931619814 return sema.fail(block, src, "Type.Fn.Param.is_generic must be false for @Type", .{});
1931719815 }
1931819816
19319 const param_type_val = param_type_opt_val.optionalValue() orelse
19817 const param_type_val = opt_param_type_val.optionalValue(mod) orelse
1932019818 return sema.fail(block, src, "Type.Fn.Param.arg_type must be non-null for @Type", .{});
19321 const param_type = try param_type_val.toType(&buf).copy(sema.arena);
19819 param_type.* = param_type_val.toIntern();
1932219820
19323 if (arg_is_noalias) {
19324 if (!param_type.isPtrAtRuntime()) {
19821 if (param_is_noalias_val.toBool()) {
19822 if (!param_type.toType().isPtrAtRuntime(mod)) {
1932519823 return sema.fail(block, src, "non-pointer parameter declared noalias", .{});
1932619824 }
1932719825 noalias_bits |= @as(u32, 1) << (std.math.cast(u5, i) orelse
1932819826 return sema.fail(block, src, "this compiler implementation only supports 'noalias' on the first 32 parameters", .{}));
1932919827 }
19330
19331 param_types[i] = param_type;
19332 comptime_params[i] = false;
1933319828 }
1933419829
19335 var fn_info = Type.Payload.Function.Data{
19830 const ty = try mod.funcType(.{
1933619831 .param_types = param_types,
19337 .comptime_params = comptime_params.ptr,
19832 .comptime_bits = 0,
1933819833 .noalias_bits = noalias_bits,
19339 .return_type = try return_type.toType(&buf).copy(sema.arena),
19834 .return_type = return_type.toIntern(),
1934019835 .alignment = alignment,
1934119836 .cc = cc,
1934219837 .is_var_args = is_var_args,
......@@ -19346,9 +19841,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in
1934619841 .cc_is_generic = false,
1934719842 .section_is_generic = false,
1934819843 .addrspace_is_generic = false,
19349 };
19350
19351 const ty = try Type.Tag.function.create(sema.arena, fn_info);
19844 });
1935219845 return sema.addType(ty);
1935319846 },
1935419847 .Frame => return sema.failWithUseOfAsync(block, src),
......@@ -19366,22 +19859,34 @@ fn reifyStruct(
1936619859 name_strategy: Zir.Inst.NameStrategy,
1936719860 is_tuple: bool,
1936819861) CompileError!Air.Inst.Ref {
19369 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
19370 errdefer new_decl_arena.deinit();
19371 const new_decl_arena_allocator = new_decl_arena.allocator();
19372
19373 const struct_obj = try new_decl_arena_allocator.create(Module.Struct);
19374 const struct_ty = try Type.Tag.@"struct".create(new_decl_arena_allocator, struct_obj);
19375 const new_struct_val = try Value.Tag.ty.create(new_decl_arena_allocator, struct_ty);
1937619862 const mod = sema.mod;
19863 const gpa = sema.gpa;
19864 const ip = &mod.intern_pool;
19865
19866 // Because these three things each reference each other, `undefined`
19867 // placeholders are used before being set after the struct type gains an
19868 // InternPool index.
19869
1937719870 const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{
19378 .ty = Type.type,
19379 .val = new_struct_val,
19871 .ty = Type.noreturn,
19872 .val = Value.@"unreachable",
1938019873 }, name_strategy, "struct", inst);
1938119874 const new_decl = mod.declPtr(new_decl_index);
1938219875 new_decl.owns_tv = true;
19383 errdefer mod.abortAnonDecl(new_decl_index);
19384 struct_obj.* = .{
19876 errdefer {
19877 new_decl.has_tv = false; // namespace and val were destroyed by later errdefers
19878 mod.abortAnonDecl(new_decl_index);
19879 }
19880
19881 const new_namespace_index = try mod.createNamespace(.{
19882 .parent = block.namespace.toOptional(),
19883 .ty = undefined,
19884 .file_scope = block.getFileScope(mod),
19885 });
19886 const new_namespace = mod.namespacePtr(new_namespace_index);
19887 errdefer mod.destroyNamespace(new_namespace_index);
19888
19889 const struct_index = try mod.createStruct(.{
1938519890 .owner_decl = new_decl_index,
1938619891 .fields = .{},
1938719892 .zir_index = inst,
......@@ -19389,38 +19894,49 @@ fn reifyStruct(
1938919894 .status = .have_field_types,
1939019895 .known_non_opv = false,
1939119896 .is_tuple = is_tuple,
19392 .namespace = .{
19393 .parent = block.namespace,
19394 .ty = struct_ty,
19395 .file_scope = block.getFileScope(),
19396 },
19397 };
19897 .namespace = new_namespace_index,
19898 });
19899 const struct_obj = mod.structPtr(struct_index);
19900 errdefer mod.destroyStruct(struct_index);
1939819901
19399 const target = mod.getTarget();
19902 const struct_ty = try ip.get(gpa, .{ .struct_type = .{
19903 .index = struct_index.toOptional(),
19904 .namespace = new_namespace_index.toOptional(),
19905 } });
19906 // TODO: figure out InternPool removals for incremental compilation
19907 //errdefer ip.remove(struct_ty);
19908
19909 new_decl.ty = Type.type;
19910 new_decl.val = struct_ty.toValue();
19911 new_namespace.ty = struct_ty.toType();
1940019912
1940119913 // Fields
1940219914 const fields_len = try sema.usizeCast(block, src, fields_val.sliceLen(mod));
19403 try struct_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
19915 try struct_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);
1940419916 var i: usize = 0;
1940519917 while (i < fields_len) : (i += 1) {
19406 const elem_val = try fields_val.elemValue(sema.mod, sema.arena, i);
19407 const field_struct_val = elem_val.castTag(.aggregate).?.data;
19408 // TODO use reflection instead of magic numbers here
19409 // name: []const u8
19410 const name_val = field_struct_val[0];
19411 // type: type,
19412 const type_val = field_struct_val[1];
19413 // default_value: ?*const anyopaque,
19414 const default_value_val = field_struct_val[2];
19415 // is_comptime: bool,
19416 const is_comptime_val = field_struct_val[3];
19417 // alignment: comptime_int,
19418 const alignment_val = field_struct_val[4];
19918 const elem_val = try fields_val.elemValue(mod, i);
19919 const elem_fields = ip.typeOf(elem_val.toIntern()).toType().structFields(mod);
19920 const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19921 try ip.getOrPutString(gpa, "name"),
19922 ).?);
19923 const type_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19924 try ip.getOrPutString(gpa, "type"),
19925 ).?);
19926 const default_value_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19927 try ip.getOrPutString(gpa, "default_value"),
19928 ).?);
19929 const is_comptime_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19930 try ip.getOrPutString(gpa, "is_comptime"),
19931 ).?);
19932 const alignment_val = try elem_val.fieldValue(mod, elem_fields.getIndex(
19933 try ip.getOrPutString(gpa, "alignment"),
19934 ).?);
1941919935
1942019936 if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
1942119937 return sema.fail(block, src, "alignment must fit in 'u32'", .{});
1942219938 }
19423 const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(target, sema)).?);
19939 const abi_align = @intCast(u29, (try alignment_val.getUnsignedIntAdvanced(mod, sema)).?);
1942419940
1942519941 if (layout == .Packed) {
1942619942 if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{});
......@@ -19430,21 +19946,15 @@ fn reifyStruct(
1943019946 return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{});
1943119947 }
1943219948
19433 const field_name = try name_val.toAllocatedBytes(
19434 Type.initTag(.const_slice_u8),
19435 new_decl_arena_allocator,
19436 mod,
19437 );
19949 const field_name = try name_val.toIpString(Type.slice_const_u8, mod);
1943819950
1943919951 if (is_tuple) {
19440 const field_index = std.fmt.parseUnsigned(u32, field_name, 10) catch {
19441 return sema.fail(
19442 block,
19443 src,
19444 "tuple cannot have non-numeric field '{s}'",
19445 .{field_name},
19446 );
19447 };
19952 const field_index = field_name.toUnsigned(ip) orelse return sema.fail(
19953 block,
19954 src,
19955 "tuple cannot have non-numeric field '{}'",
19956 .{field_name.fmt(ip)},
19957 );
1944819958
1944919959 if (field_index >= fields_len) {
1945019960 return sema.fail(
......@@ -19458,22 +19968,19 @@ fn reifyStruct(
1945819968 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
1945919969 if (gop.found_existing) {
1946019970 // TODO: better source location
19461 return sema.fail(block, src, "duplicate struct field {s}", .{field_name});
19971 return sema.fail(block, src, "duplicate struct field {}", .{field_name.fmt(ip)});
1946219972 }
1946319973
19464 const default_val = if (default_value_val.optionalValue()) |opt_val| blk: {
19465 const payload_val = if (opt_val.pointerDecl()) |opt_decl|
19466 mod.declPtr(opt_decl).val
19467 else
19468 opt_val;
19469 break :blk try payload_val.copy(new_decl_arena_allocator);
19470 } else Value.initTag(.unreachable_value);
19471 if (is_comptime_val.toBool() and default_val.tag() == .unreachable_value) {
19974 const field_ty = type_val.toType();
19975 const default_val = if (default_value_val.optionalValue(mod)) |opt_val|
19976 (try sema.pointerDeref(block, src, opt_val, try mod.singleConstPtrType(field_ty)) orelse
19977 return sema.failWithNeededComptime(block, src, "struct field default value must be comptime-known")).toIntern()
19978 else
19979 .none;
19980 if (is_comptime_val.toBool() and default_val == .none) {
1947219981 return sema.fail(block, src, "comptime field without default initialization value", .{});
1947319982 }
1947419983
19475 var buffer: Value.ToTypeBuffer = undefined;
19476 const field_ty = try type_val.toType(&buffer).copy(new_decl_arena_allocator);
1947719984 gop.value_ptr.* = .{
1947819985 .ty = field_ty,
1947919986 .abi_align = abi_align,
......@@ -19482,20 +19989,20 @@ fn reifyStruct(
1948219989 .offset = undefined,
1948319990 };
1948419991
19485 if (field_ty.zigTypeTag() == .Opaque) {
19992 if (field_ty.zigTypeTag(mod) == .Opaque) {
1948619993 const msg = msg: {
1948719994 const msg = try sema.errMsg(block, src, "opaque types have unknown size and therefore cannot be directly embedded in structs", .{});
19488 errdefer msg.destroy(sema.gpa);
19995 errdefer msg.destroy(gpa);
1948919996
1949019997 try sema.addDeclaredHereNote(msg, field_ty);
1949119998 break :msg msg;
1949219999 };
1949320000 return sema.failWithOwnedErrorMsg(msg);
1949420001 }
19495 if (field_ty.zigTypeTag() == .NoReturn) {
20002 if (field_ty.zigTypeTag(mod) == .NoReturn) {
1949620003 const msg = msg: {
1949720004 const msg = try sema.errMsg(block, src, "struct fields cannot be 'noreturn'", .{});
19498 errdefer msg.destroy(sema.gpa);
20005 errdefer msg.destroy(gpa);
1949920006
1950020007 try sema.addDeclaredHereNote(msg, field_ty);
1950120008 break :msg msg;
......@@ -19505,22 +20012,22 @@ fn reifyStruct(
1950520012 if (struct_obj.layout == .Extern and !try sema.validateExternType(field_ty, .struct_field)) {
1950620013 const msg = msg: {
1950720014 const msg = try sema.errMsg(block, src, "extern structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
19508 errdefer msg.destroy(sema.gpa);
20015 errdefer msg.destroy(gpa);
1950920016
1951020017 const src_decl = sema.mod.declPtr(block.src_decl);
19511 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), field_ty, .struct_field);
20018 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), field_ty, .struct_field);
1951220019
1951320020 try sema.addDeclaredHereNote(msg, field_ty);
1951420021 break :msg msg;
1951520022 };
1951620023 return sema.failWithOwnedErrorMsg(msg);
19517 } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty))) {
20024 } else if (struct_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) {
1951820025 const msg = msg: {
1951920026 const msg = try sema.errMsg(block, src, "packed structs cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
19520 errdefer msg.destroy(sema.gpa);
20027 errdefer msg.destroy(gpa);
1952120028
1952220029 const src_decl = sema.mod.declPtr(block.src_decl);
19523 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl), field_ty);
20030 try sema.explainWhyTypeIsNotPacked(msg, src.toSrcLoc(src_decl, mod), field_ty);
1952420031
1952520032 try sema.addDeclaredHereNote(msg, field_ty);
1952620033 break :msg msg;
......@@ -19536,7 +20043,7 @@ fn reifyStruct(
1953620043 sema.resolveTypeLayout(field.ty) catch |err| switch (err) {
1953720044 error.AnalysisFail => {
1953820045 const msg = sema.err orelse return err;
19539 try sema.addFieldErrNote(struct_ty, index, msg, "while checking this field", .{});
20046 try sema.addFieldErrNote(struct_ty.toType(), index, msg, "while checking this field", .{});
1954020047 return err;
1954120048 },
1954220049 else => return err,
......@@ -19545,30 +20052,27 @@ fn reifyStruct(
1954520052
1954620053 var fields_bit_sum: u64 = 0;
1954720054 for (struct_obj.fields.values()) |field| {
19548 fields_bit_sum += field.ty.bitSize(target);
20055 fields_bit_sum += field.ty.bitSize(mod);
1954920056 }
1955020057
19551 if (backing_int_val.optionalValue()) |payload| {
19552 var buf: Value.ToTypeBuffer = undefined;
19553 const backing_int_ty = payload.toType(&buf);
20058 if (backing_int_val.optionalValue(mod)) |payload| {
20059 const backing_int_ty = payload.toType();
1955420060 try sema.checkBackingIntType(block, src, backing_int_ty, fields_bit_sum);
19555 struct_obj.backing_int_ty = try backing_int_ty.copy(new_decl_arena_allocator);
20061 struct_obj.backing_int_ty = backing_int_ty;
1955620062 } else {
19557 var buf: Type.Payload.Bits = .{
19558 .base = .{ .tag = .int_unsigned },
19559 .data = @intCast(u16, fields_bit_sum),
19560 };
19561 struct_obj.backing_int_ty = try Type.initPayload(&buf.base).copy(new_decl_arena_allocator);
20063 struct_obj.backing_int_ty = try mod.intType(.unsigned, @intCast(u16, fields_bit_sum));
1956220064 }
1956320065
1956420066 struct_obj.status = .have_layout;
1956520067 }
1956620068
19567 try new_decl.finalizeNewArena(&new_decl_arena);
19568 return sema.analyzeDeclVal(block, src, new_decl_index);
20069 const decl_val = sema.analyzeDeclVal(block, src, new_decl_index);
20070 try mod.finalizeAnonDecl(new_decl_index);
20071 return decl_val;
1956920072}
1957020073
1957120074fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20075 const mod = sema.mod;
1957220076 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
1957320077 const src = LazySrcLoc.nodeOffset(extra.node);
1957420078 const addrspace_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -19580,7 +20084,7 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
1958020084
1958120085 try sema.checkPtrOperand(block, ptr_src, ptr_ty);
1958220086
19583 var ptr_info = ptr_ty.ptrInfo().data;
20087 var ptr_info = ptr_ty.ptrInfo(mod);
1958420088 const src_addrspace = ptr_info.@"addrspace";
1958520089 if (!target_util.addrSpaceCastIsValid(sema.mod.getTarget(), src_addrspace, dest_addrspace)) {
1958620090 const msg = msg: {
......@@ -19594,8 +20098,8 @@ fn zirAddrSpaceCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst
1959420098
1959520099 ptr_info.@"addrspace" = dest_addrspace;
1959620100 const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
19597 const dest_ty = if (ptr_ty.zigTypeTag() == .Optional)
19598 try Type.optional(sema.arena, dest_ptr_ty)
20101 const dest_ty = if (ptr_ty.zigTypeTag(mod) == .Optional)
20102 try Type.optional(sema.arena, dest_ptr_ty, mod)
1959920103 else
1960020104 dest_ptr_ty;
1960120105
......@@ -19624,6 +20128,7 @@ fn resolveVaListRef(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.In
1962420128}
1962520129
1962620130fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20131 const mod = sema.mod;
1962720132 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
1962820133 const src = LazySrcLoc.nodeOffset(extra.node);
1962920134 const va_list_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -19638,7 +20143,7 @@ fn zirCVaArg(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
1963820143 errdefer msg.destroy(sema.gpa);
1963920144
1964020145 const src_decl = sema.mod.declPtr(block.src_decl);
19641 try sema.explainWhyTypeIsNotExtern(msg, ty_src.toSrcLoc(src_decl), arg_ty, .param_ty);
20146 try sema.explainWhyTypeIsNotExtern(msg, ty_src.toSrcLoc(src_decl, mod), arg_ty, .param_ty);
1964220147
1964320148 try sema.addDeclaredHereNote(msg, arg_ty);
1964420149 break :msg msg;
......@@ -19685,6 +20190,7 @@ fn zirCVaStart(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData)
1968520190}
1968620191
1968720192fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20193 const mod = sema.mod;
1968820194 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1968920195 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1969020196 const ty = try sema.resolveType(block, ty_src, inst_data.operand);
......@@ -19692,11 +20198,19 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1969220198 var anon_decl = try block.startAnonDecl();
1969320199 defer anon_decl.deinit();
1969420200
19695 const bytes = try ty.nameAllocArena(anon_decl.arena(), sema.mod);
20201 const bytes = try ty.nameAllocArena(sema.arena, mod);
1969620202
20203 const decl_ty = try mod.arrayType(.{
20204 .len = bytes.len,
20205 .child = .u8_type,
20206 .sentinel = .zero_u8,
20207 });
1969720208 const new_decl = try anon_decl.finish(
19698 try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
19699 try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
20209 decl_ty,
20210 (try mod.intern(.{ .aggregate = .{
20211 .ty = decl_ty.toIntern(),
20212 .storage = .{ .bytes = bytes },
20213 } })).toValue(),
1970020214 0, // default alignment
1970120215 );
1970220216
......@@ -19716,6 +20230,7 @@ fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
1971620230}
1971720231
1971820232fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20233 const mod = sema.mod;
1971920234 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1972020235 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1972120236 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
......@@ -19730,24 +20245,24 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1973020245 if (try sema.resolveMaybeUndefVal(operand)) |val| {
1973120246 const result_val = try sema.floatToInt(block, operand_src, val, operand_ty, dest_ty);
1973220247 return sema.addConstant(dest_ty, result_val);
19733 } else if (dest_ty.zigTypeTag() == .ComptimeInt) {
20248 } else if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {
1973420249 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_int' must be comptime-known");
1973520250 }
1973620251
1973720252 try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
19738 if (dest_ty.intInfo(sema.mod.getTarget()).bits == 0) {
20253 if (dest_ty.intInfo(mod).bits == 0) {
1973920254 if (block.wantSafety()) {
19740 const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, Value.zero));
20255 const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0)));
1974120256 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
1974220257 }
19743 return sema.addConstant(dest_ty, Value.zero);
20258 return sema.addConstant(dest_ty, try mod.intValue(dest_ty, 0));
1974420259 }
1974520260 const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
1974620261 if (block.wantSafety()) {
1974720262 const back = try block.addTyOp(.int_to_float, operand_ty, result);
1974820263 const diff = try block.addBinOp(.sub, operand, back);
19749 const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, Value.one));
19750 const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_one));
20264 const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, try mod.floatValue(operand_ty, 1.0)));
20265 const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, try mod.floatValue(operand_ty, -1.0)));
1975120266 const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
1975220267 try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
1975320268 }
......@@ -19755,6 +20270,7 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1975520270}
1975620271
1975720272fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20273 const mod = sema.mod;
1975820274 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1975920275 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
1976020276 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
......@@ -19769,7 +20285,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1976920285 if (try sema.resolveMaybeUndefVal(operand)) |val| {
1977020286 const result_val = try val.intToFloatAdvanced(sema.arena, operand_ty, dest_ty, sema.mod, sema);
1977120287 return sema.addConstant(dest_ty, result_val);
19772 } else if (dest_ty.zigTypeTag() == .ComptimeFloat) {
20288 } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) {
1977320289 return sema.failWithNeededComptime(block, operand_src, "value being casted to 'comptime_float' must be comptime-known");
1977420290 }
1977520291
......@@ -19778,6 +20294,7 @@ fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
1977820294}
1977920295
1978020296fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20297 const mod = sema.mod;
1978120298 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1978220299 const src = inst_data.src();
1978320300
......@@ -19790,11 +20307,10 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1979020307 const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1979120308 const ptr_ty = try sema.resolveType(block, src, extra.lhs);
1979220309 try sema.checkPtrType(block, type_src, ptr_ty);
19793 const elem_ty = ptr_ty.elemType2();
19794 const target = sema.mod.getTarget();
19795 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(target, sema);
20310 const elem_ty = ptr_ty.elemType2(mod);
20311 const ptr_align = try ptr_ty.ptrAlignmentAdvanced(mod, sema);
1979620312
19797 if (ptr_ty.isSlice()) {
20313 if (ptr_ty.isSlice(mod)) {
1979820314 const msg = msg: {
1979920315 const msg = try sema.errMsg(block, type_src, "integer cannot be converted to slice type '{}'", .{ptr_ty.fmt(sema.mod)});
1980020316 errdefer msg.destroy(sema.gpa);
......@@ -19805,36 +20321,26 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1980520321 }
1980620322
1980720323 if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| {
19808 const addr = val.toUnsignedInt(target);
19809 if (!ptr_ty.isAllowzeroPtr() and addr == 0)
20324 const addr = val.toUnsignedInt(mod);
20325 if (!ptr_ty.isAllowzeroPtr(mod) and addr == 0)
1981020326 return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{ptr_ty.fmt(sema.mod)});
1981120327 if (addr != 0 and ptr_align != 0 and addr % ptr_align != 0)
1981220328 return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{ptr_ty.fmt(sema.mod)});
1981320329
19814 const val_payload = try sema.arena.create(Value.Payload.U64);
19815 val_payload.* = .{
19816 .base = .{ .tag = .int_u64 },
19817 .data = addr,
19818 };
19819 return sema.addConstant(ptr_ty, Value.initPayload(&val_payload.base));
20330 return sema.addConstant(ptr_ty, try mod.ptrIntValue(ptr_ty, addr));
1982020331 }
1982120332
1982220333 try sema.requireRuntimeBlock(block, src, operand_src);
19823 if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag() == .Fn)) {
19824 if (!ptr_ty.isAllowzeroPtr()) {
20334 if (block.wantSafety() and (try sema.typeHasRuntimeBits(elem_ty) or elem_ty.zigTypeTag(mod) == .Fn)) {
20335 if (!ptr_ty.isAllowzeroPtr(mod)) {
1982520336 const is_non_zero = try block.addBinOp(.cmp_neq, operand_coerced, .zero_usize);
1982620337 try sema.addSafetyCheck(block, is_non_zero, .cast_to_null);
1982720338 }
1982820339
1982920340 if (ptr_align > 1) {
19830 const val_payload = try sema.arena.create(Value.Payload.U64);
19831 val_payload.* = .{
19832 .base = .{ .tag = .int_u64 },
19833 .data = ptr_align - 1,
19834 };
1983520341 const align_minus_1 = try sema.addConstant(
1983620342 Type.usize,
19837 Value.initPayload(&val_payload.base),
20343 try mod.intValue(Type.usize, ptr_align - 1),
1983820344 );
1983920345 const remainder = try block.addBinOp(.bit_and, operand_coerced, align_minus_1);
1984020346 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
......@@ -19845,6 +20351,8 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
1984520351}
1984620352
1984720353fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20354 const mod = sema.mod;
20355 const ip = &mod.intern_pool;
1984820356 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
1984920357 const src = LazySrcLoc.nodeOffset(extra.node);
1985020358 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -19860,22 +20368,27 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1986020368
1986120369 if (disjoint: {
1986220370 // Try avoiding resolving inferred error sets if we can
19863 if (!dest_ty.isAnyError() and dest_ty.errorSetNames().len == 0) break :disjoint true;
19864 if (!operand_ty.isAnyError() and operand_ty.errorSetNames().len == 0) break :disjoint true;
19865 if (dest_ty.isAnyError()) break :disjoint false;
19866 if (operand_ty.isAnyError()) break :disjoint false;
19867 for (dest_ty.errorSetNames()) |dest_err_name|
19868 if (operand_ty.errorSetHasField(dest_err_name))
20371 if (!dest_ty.isAnyError(mod) and dest_ty.errorSetNames(mod).len == 0) break :disjoint true;
20372 if (!operand_ty.isAnyError(mod) and operand_ty.errorSetNames(mod).len == 0) break :disjoint true;
20373 if (dest_ty.isAnyError(mod)) break :disjoint false;
20374 if (operand_ty.isAnyError(mod)) break :disjoint false;
20375 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
20376 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
1986920377 break :disjoint false;
20378 }
1987020379
19871 if (dest_ty.tag() != .error_set_inferred and operand_ty.tag() != .error_set_inferred)
20380 if (!ip.isInferredErrorSetType(dest_ty.toIntern()) and
20381 !ip.isInferredErrorSetType(operand_ty.toIntern()))
20382 {
1987220383 break :disjoint true;
20384 }
1987320385
1987420386 try sema.resolveInferredErrorSetTy(block, dest_ty_src, dest_ty);
1987520387 try sema.resolveInferredErrorSetTy(block, operand_src, operand_ty);
19876 for (dest_ty.errorSetNames()) |dest_err_name|
19877 if (operand_ty.errorSetHasField(dest_err_name))
20388 for (dest_ty.errorSetNames(mod)) |dest_err_name| {
20389 if (Type.errorSetHasFieldIp(ip, operand_ty.toIntern(), dest_err_name))
1987820390 break :disjoint false;
20391 }
1987920392
1988020393 break :disjoint true;
1988120394 }) {
......@@ -19895,15 +20408,15 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1989520408 }
1989620409
1989720410 if (maybe_operand_val) |val| {
19898 if (!dest_ty.isAnyError()) {
19899 const error_name = val.castTag(.@"error").?.data.name;
19900 if (!dest_ty.errorSetHasField(error_name)) {
20411 if (!dest_ty.isAnyError(mod)) {
20412 const error_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
20413 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), error_name)) {
1990120414 const msg = msg: {
1990220415 const msg = try sema.errMsg(
1990320416 block,
1990420417 src,
19905 "'error.{s}' not a member of error set '{}'",
19906 .{ error_name, dest_ty.fmt(sema.mod) },
20418 "'error.{}' not a member of error set '{}'",
20419 .{ error_name.fmt(ip), dest_ty.fmt(sema.mod) },
1990720420 );
1990820421 errdefer msg.destroy(sema.gpa);
1990920422 try sema.addDeclaredHereNote(msg, dest_ty);
......@@ -19913,11 +20426,11 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1991320426 }
1991420427 }
1991520428
19916 return sema.addConstant(dest_ty, val);
20429 return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
1991720430 }
1991820431
1991920432 try sema.requireRuntimeBlock(block, src, operand_src);
19920 if (block.wantSafety() and !dest_ty.isAnyError() and sema.mod.backendSupportsFeature(.error_set_has_value)) {
20433 if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {
1992120434 const err_int_inst = try block.addBitCast(Type.err_int, operand);
1992220435 const ok = try block.addTyOp(.error_set_has_value, dest_ty, err_int_inst);
1992320436 try sema.addSafetyCheck(block, ok, .invalid_error_code);
......@@ -19926,6 +20439,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
1992620439}
1992720440
1992820441fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20442 const mod = sema.mod;
1992920443 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
1993020444 const src = inst_data.src();
1993120445 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
......@@ -19934,13 +20448,12 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1993420448 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
1993520449 const operand = try sema.resolveInst(extra.rhs);
1993620450 const operand_ty = sema.typeOf(operand);
19937 const target = sema.mod.getTarget();
1993820451
1993920452 try sema.checkPtrType(block, dest_ty_src, dest_ty);
1994020453 try sema.checkPtrOperand(block, operand_src, operand_ty);
1994120454
19942 const operand_info = operand_ty.ptrInfo().data;
19943 const dest_info = dest_ty.ptrInfo().data;
20455 const operand_info = operand_ty.ptrInfo(mod);
20456 const dest_info = dest_ty.ptrInfo(mod);
1994420457 if (!operand_info.mutable and dest_info.mutable) {
1994520458 const msg = msg: {
1994620459 const msg = try sema.errMsg(block, src, "cast discards const qualifier", .{});
......@@ -19972,8 +20485,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1997220485 return sema.failWithOwnedErrorMsg(msg);
1997320486 }
1997420487
19975 const dest_is_slice = dest_ty.isSlice();
19976 const operand_is_slice = operand_ty.isSlice();
20488 const dest_is_slice = dest_ty.isSlice(mod);
20489 const operand_is_slice = operand_ty.isSlice(mod);
1997720490 if (dest_is_slice and !operand_is_slice) {
1997820491 return sema.fail(block, dest_ty_src, "illegal pointer cast to slice", .{});
1997920492 }
......@@ -19982,32 +20495,31 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
1998220495 else
1998320496 operand;
1998420497
19985 const dest_elem_ty = dest_ty.elemType2();
20498 const dest_elem_ty = dest_ty.elemType2(mod);
1998620499 try sema.resolveTypeLayout(dest_elem_ty);
19987 const dest_align = dest_ty.ptrAlignment(target);
20500 const dest_align = dest_ty.ptrAlignment(mod);
1998820501
19989 const operand_elem_ty = operand_ty.elemType2();
20502 const operand_elem_ty = operand_ty.elemType2(mod);
1999020503 try sema.resolveTypeLayout(operand_elem_ty);
19991 const operand_align = operand_ty.ptrAlignment(target);
20504 const operand_align = operand_ty.ptrAlignment(mod);
1999220505
1999320506 // If the destination is less aligned than the source, preserve the source alignment
1999420507 const aligned_dest_ty = if (operand_align <= dest_align) dest_ty else blk: {
1999520508 // Unwrap the pointer (or pointer-like optional) type, set alignment, and re-wrap into result
19996 if (dest_ty.zigTypeTag() == .Optional) {
19997 var buf: Type.Payload.ElemType = undefined;
19998 var dest_ptr_info = dest_ty.optionalChild(&buf).ptrInfo().data;
20509 if (dest_ty.zigTypeTag(mod) == .Optional) {
20510 var dest_ptr_info = dest_ty.optionalChild(mod).ptrInfo(mod);
1999920511 dest_ptr_info.@"align" = operand_align;
20000 break :blk try Type.optional(sema.arena, try Type.ptr(sema.arena, sema.mod, dest_ptr_info));
20512 break :blk try Type.optional(sema.arena, try Type.ptr(sema.arena, mod, dest_ptr_info), mod);
2000120513 } else {
20002 var dest_ptr_info = dest_ty.ptrInfo().data;
20514 var dest_ptr_info = dest_ty.ptrInfo(mod);
2000320515 dest_ptr_info.@"align" = operand_align;
20004 break :blk try Type.ptr(sema.arena, sema.mod, dest_ptr_info);
20516 break :blk try Type.ptr(sema.arena, mod, dest_ptr_info);
2000520517 }
2000620518 };
2000720519
2000820520 if (dest_is_slice) {
20009 const operand_elem_size = operand_elem_ty.abiSize(target);
20010 const dest_elem_size = dest_elem_ty.abiSize(target);
20521 const operand_elem_size = operand_elem_ty.abiSize(mod);
20522 const dest_elem_size = dest_elem_ty.abiSize(mod);
2001120523 if (operand_elem_size != dest_elem_size) {
2001220524 return sema.fail(block, dest_ty_src, "TODO: implement @ptrCast between slices changing the length", .{});
2001320525 }
......@@ -20019,10 +20531,10 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2001920531 errdefer msg.destroy(sema.gpa);
2002020532
2002120533 try sema.errNote(block, operand_src, msg, "'{}' has alignment '{d}'", .{
20022 operand_ty.fmt(sema.mod), operand_align,
20534 operand_ty.fmt(mod), operand_align,
2002320535 });
2002420536 try sema.errNote(block, dest_ty_src, msg, "'{}' has alignment '{d}'", .{
20025 dest_ty.fmt(sema.mod), dest_align,
20537 dest_ty.fmt(mod), dest_align,
2002620538 });
2002720539
2002820540 try sema.errNote(block, src, msg, "consider using '@alignCast'", .{});
......@@ -20032,21 +20544,18 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2003220544 }
2003320545
2003420546 if (try sema.resolveMaybeUndefVal(ptr)) |operand_val| {
20035 if (!dest_ty.ptrAllowsZero() and operand_val.isUndef()) {
20547 if (!dest_ty.ptrAllowsZero(mod) and operand_val.isUndef(mod)) {
2003620548 return sema.failWithUseOfUndef(block, operand_src);
2003720549 }
20038 if (!dest_ty.ptrAllowsZero() and operand_val.isNull()) {
20039 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
20040 }
20041 if (dest_ty.zigTypeTag() == .Optional and sema.typeOf(ptr).zigTypeTag() != .Optional) {
20042 return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, operand_val));
20550 if (!dest_ty.ptrAllowsZero(mod) and operand_val.isNull(mod)) {
20551 return sema.fail(block, operand_src, "null pointer casted to type '{}'", .{dest_ty.fmt(mod)});
2004320552 }
20044 return sema.addConstant(aligned_dest_ty, operand_val);
20553 return sema.addConstant(aligned_dest_ty, try mod.getCoerced(operand_val, aligned_dest_ty));
2004520554 }
2004620555
2004720556 try sema.requireRuntimeBlock(block, src, null);
20048 if (block.wantSafety() and operand_ty.ptrAllowsZero() and !dest_ty.ptrAllowsZero() and
20049 (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn))
20557 if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and
20558 (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn))
2005020559 {
2005120560 const ptr_int = try block.addUnOp(.ptrtoint, ptr);
2005220561 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
......@@ -20062,6 +20571,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2006220571}
2006320572
2006420573fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20574 const mod = sema.mod;
2006520575 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
2006620576 const src = LazySrcLoc.nodeOffset(extra.node);
2006720577 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -20069,12 +20579,12 @@ fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2006920579 const operand_ty = sema.typeOf(operand);
2007020580 try sema.checkPtrOperand(block, operand_src, operand_ty);
2007120581
20072 var ptr_info = operand_ty.ptrInfo().data;
20582 var ptr_info = operand_ty.ptrInfo(mod);
2007320583 ptr_info.mutable = true;
20074 const dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
20584 const dest_ty = try Type.ptr(sema.arena, mod, ptr_info);
2007520585
2007620586 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
20077 return sema.addConstant(dest_ty, operand_val);
20587 return sema.addConstant(dest_ty, try mod.getCoerced(operand_val, dest_ty));
2007820588 }
2007920589
2008020590 try sema.requireRuntimeBlock(block, src, null);
......@@ -20082,6 +20592,7 @@ fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2008220592}
2008320593
2008420594fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
20595 const mod = sema.mod;
2008520596 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
2008620597 const src = LazySrcLoc.nodeOffset(extra.node);
2008720598 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
......@@ -20089,9 +20600,9 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
2008920600 const operand_ty = sema.typeOf(operand);
2009020601 try sema.checkPtrOperand(block, operand_src, operand_ty);
2009120602
20092 var ptr_info = operand_ty.ptrInfo().data;
20603 var ptr_info = operand_ty.ptrInfo(mod);
2009320604 ptr_info.@"volatile" = false;
20094 const dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
20605 const dest_ty = try Type.ptr(sema.arena, mod, ptr_info);
2009520606
2009620607 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
2009720608 return sema.addConstant(dest_ty, operand_val);
......@@ -20102,6 +20613,7 @@ fn zirVolatileCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
2010220613}
2010320614
2010420615fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20616 const mod = sema.mod;
2010520617 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2010620618 const src = inst_data.src();
2010720619 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
......@@ -20112,9 +20624,12 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2011220624 const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_scalar_ty);
2011320625 const operand_ty = sema.typeOf(operand);
2011420626 const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src);
20115 const is_vector = operand_ty.zigTypeTag() == .Vector;
20627 const is_vector = operand_ty.zigTypeTag(mod) == .Vector;
2011620628 const dest_ty = if (is_vector)
20117 try Type.vector(sema.arena, operand_ty.vectorLen(), dest_scalar_ty)
20629 try mod.vectorType(.{
20630 .len = operand_ty.vectorLen(mod),
20631 .child = dest_scalar_ty.toIntern(),
20632 })
2011820633 else
2011920634 dest_scalar_ty;
2012020635
......@@ -20122,22 +20637,21 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2012220637 return sema.coerce(block, dest_ty, operand, operand_src);
2012320638 }
2012420639
20125 const target = sema.mod.getTarget();
20126 const dest_info = dest_scalar_ty.intInfo(target);
20640 const dest_info = dest_scalar_ty.intInfo(mod);
2012720641
2012820642 if (try sema.typeHasOnePossibleValue(dest_ty)) |val| {
2012920643 return sema.addConstant(dest_ty, val);
2013020644 }
2013120645
20132 if (operand_scalar_ty.zigTypeTag() != .ComptimeInt) {
20133 const operand_info = operand_ty.intInfo(target);
20646 if (operand_scalar_ty.zigTypeTag(mod) != .ComptimeInt) {
20647 const operand_info = operand_ty.intInfo(mod);
2013420648 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
2013520649 return sema.addConstant(operand_ty, val);
2013620650 }
2013720651
2013820652 if (operand_info.signedness != dest_info.signedness) {
2013920653 return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{
20140 @tagName(dest_info.signedness), operand_ty.fmt(sema.mod),
20654 @tagName(dest_info.signedness), operand_ty.fmt(mod),
2014120655 });
2014220656 }
2014320657 if (operand_info.bits < dest_info.bits) {
......@@ -20146,7 +20660,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2014620660 block,
2014720661 src,
2014820662 "destination type '{}' has more bits than source type '{}'",
20149 .{ dest_ty.fmt(sema.mod), operand_ty.fmt(sema.mod) },
20663 .{ dest_ty.fmt(mod), operand_ty.fmt(mod) },
2015020664 );
2015120665 errdefer msg.destroy(sema.gpa);
2015220666 try sema.errNote(block, dest_ty_src, msg, "destination type has {d} bits", .{
......@@ -20162,23 +20676,22 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2016220676 }
2016320677
2016420678 if (try sema.resolveMaybeUndefValIntable(operand)) |val| {
20165 if (val.isUndef()) return sema.addConstUndef(dest_ty);
20679 if (val.isUndef(mod)) return sema.addConstUndef(dest_ty);
2016620680 if (!is_vector) {
20167 return sema.addConstant(
20681 return sema.addConstant(dest_ty, try mod.getCoerced(
20682 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, mod),
2016820683 dest_ty,
20169 try val.intTrunc(operand_ty, sema.arena, dest_info.signedness, dest_info.bits, sema.mod),
20170 );
20684 ));
2017120685 }
20172 var elem_buf: Value.ElemValueBuffer = undefined;
20173 const elems = try sema.arena.alloc(Value, operand_ty.vectorLen());
20686 const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod));
2017420687 for (elems, 0..) |*elem, i| {
20175 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);
20176 elem.* = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, sema.mod);
20688 const elem_val = try val.elemValue(mod, i);
20689 elem.* = try (try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, mod)).intern(dest_scalar_ty, mod);
2017720690 }
20178 return sema.addConstant(
20179 dest_ty,
20180 try Value.Tag.aggregate.create(sema.arena, elems),
20181 );
20691 return sema.addConstant(dest_ty, (try mod.intern(.{ .aggregate = .{
20692 .ty = dest_ty.toIntern(),
20693 .storage = .{ .elems = elems },
20694 } })).toValue());
2018220695 }
2018320696
2018420697 try sema.requireRuntimeBlock(block, src, operand_src);
......@@ -20186,6 +20699,7 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2018620699}
2018720700
2018820701fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20702 const mod = sema.mod;
2018920703 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2019020704 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2019120705 const align_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
......@@ -20196,43 +20710,38 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2019620710
2019720711 try sema.checkPtrOperand(block, ptr_src, ptr_ty);
2019820712
20199 var ptr_info = ptr_ty.ptrInfo().data;
20713 var ptr_info = ptr_ty.ptrInfo(mod);
2020020714 ptr_info.@"align" = dest_align;
20201 var dest_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
20202 if (ptr_ty.zigTypeTag() == .Optional) {
20203 dest_ty = try Type.Tag.optional.create(sema.arena, dest_ty);
20715 var dest_ty = try Type.ptr(sema.arena, mod, ptr_info);
20716 if (ptr_ty.zigTypeTag(mod) == .Optional) {
20717 dest_ty = try mod.optionalType(dest_ty.toIntern());
2020420718 }
2020520719
2020620720 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |val| {
20207 if (try val.getUnsignedIntAdvanced(sema.mod.getTarget(), null)) |addr| {
20721 if (try val.getUnsignedIntAdvanced(mod, null)) |addr| {
2020820722 if (addr % dest_align != 0) {
2020920723 return sema.fail(block, ptr_src, "pointer address 0x{X} is not aligned to {d} bytes", .{ addr, dest_align });
2021020724 }
2021120725 }
20212 return sema.addConstant(dest_ty, val);
20726 return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
2021320727 }
2021420728
2021520729 try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
2021620730 if (block.wantSafety() and dest_align > 1 and
2021720731 try sema.typeHasRuntimeBits(ptr_info.pointee_type))
2021820732 {
20219 const val_payload = try sema.arena.create(Value.Payload.U64);
20220 val_payload.* = .{
20221 .base = .{ .tag = .int_u64 },
20222 .data = dest_align - 1,
20223 };
2022420733 const align_minus_1 = try sema.addConstant(
2022520734 Type.usize,
20226 Value.initPayload(&val_payload.base),
20735 try mod.intValue(Type.usize, dest_align - 1),
2022720736 );
20228 const actual_ptr = if (ptr_ty.isSlice())
20737 const actual_ptr = if (ptr_ty.isSlice(mod))
2022920738 try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty)
2023020739 else
2023120740 ptr;
2023220741 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
2023320742 const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1);
2023420743 const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize);
20235 const ok = if (ptr_ty.isSlice()) ok: {
20744 const ok = if (ptr_ty.isSlice(mod)) ok: {
2023620745 const len = try sema.analyzeSliceLen(block, ptr_src, ptr);
2023720746 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
2023820747 break :ok try block.addBinOp(.bit_or, len_zero, is_aligned);
......@@ -20247,51 +20756,52 @@ fn zirBitCount(
2024720756 block: *Block,
2024820757 inst: Zir.Inst.Index,
2024920758 air_tag: Air.Inst.Tag,
20250 comptime comptimeOp: fn (val: Value, ty: Type, target: std.Target) u64,
20759 comptime comptimeOp: fn (val: Value, ty: Type, mod: *Module) u64,
2025120760) CompileError!Air.Inst.Ref {
20761 const mod = sema.mod;
2025220762 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2025320763 const src = inst_data.src();
2025420764 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2025520765 const operand = try sema.resolveInst(inst_data.operand);
2025620766 const operand_ty = sema.typeOf(operand);
2025720767 _ = try sema.checkIntOrVector(block, operand, operand_src);
20258 const target = sema.mod.getTarget();
20259 const bits = operand_ty.intInfo(target).bits;
20768 const bits = operand_ty.intInfo(mod).bits;
2026020769
2026120770 if (try sema.typeHasOnePossibleValue(operand_ty)) |val| {
2026220771 return sema.addConstant(operand_ty, val);
2026320772 }
2026420773
20265 const result_scalar_ty = try Type.smallestUnsignedInt(sema.arena, bits);
20266 switch (operand_ty.zigTypeTag()) {
20774 const result_scalar_ty = try mod.smallestUnsignedInt(bits);
20775 switch (operand_ty.zigTypeTag(mod)) {
2026720776 .Vector => {
20268 const vec_len = operand_ty.vectorLen();
20269 const result_ty = try Type.vector(sema.arena, vec_len, result_scalar_ty);
20777 const vec_len = operand_ty.vectorLen(mod);
20778 const result_ty = try mod.vectorType(.{
20779 .len = vec_len,
20780 .child = result_scalar_ty.toIntern(),
20781 });
2027020782 if (try sema.resolveMaybeUndefVal(operand)) |val| {
20271 if (val.isUndef()) return sema.addConstUndef(result_ty);
20783 if (val.isUndef(mod)) return sema.addConstUndef(result_ty);
2027220784
20273 var elem_buf: Value.ElemValueBuffer = undefined;
20274 const elems = try sema.arena.alloc(Value, vec_len);
20275 const scalar_ty = operand_ty.scalarType();
20785 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
20786 const scalar_ty = operand_ty.scalarType(mod);
2027620787 for (elems, 0..) |*elem, i| {
20277 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);
20278 const count = comptimeOp(elem_val, scalar_ty, target);
20279 elem.* = try Value.Tag.int_u64.create(sema.arena, count);
20280 }
20281 return sema.addConstant(
20282 result_ty,
20283 try Value.Tag.aggregate.create(sema.arena, elems),
20284 );
20788 const elem_val = try val.elemValue(mod, i);
20789 const count = comptimeOp(elem_val, scalar_ty, mod);
20790 elem.* = (try mod.intValue(result_scalar_ty, count)).toIntern();
20791 }
20792 return sema.addConstant(result_ty, (try mod.intern(.{ .aggregate = .{
20793 .ty = result_ty.toIntern(),
20794 .storage = .{ .elems = elems },
20795 } })).toValue());
2028520796 } else {
2028620797 try sema.requireRuntimeBlock(block, src, operand_src);
2028720798 return block.addTyOp(air_tag, result_ty, operand);
2028820799 }
2028920800 },
2029020801 .Int => {
20291 if (try sema.resolveMaybeUndefVal(operand)) |val| {
20292 if (val.isUndef()) return sema.addConstUndef(result_scalar_ty);
20293 try sema.resolveLazyValue(val);
20294 return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, target));
20802 if (try sema.resolveMaybeUndefLazyVal(operand)) |val| {
20803 if (val.isUndef(mod)) return sema.addConstUndef(result_scalar_ty);
20804 return sema.addIntUnsigned(result_scalar_ty, comptimeOp(val, operand_ty, mod));
2029520805 } else {
2029620806 try sema.requireRuntimeBlock(block, src, operand_src);
2029720807 return block.addTyOp(air_tag, result_scalar_ty, operand);
......@@ -20302,20 +20812,20 @@ fn zirBitCount(
2030220812}
2030320813
2030420814fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
20815 const mod = sema.mod;
2030520816 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2030620817 const src = inst_data.src();
2030720818 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2030820819 const operand = try sema.resolveInst(inst_data.operand);
2030920820 const operand_ty = sema.typeOf(operand);
2031020821 const scalar_ty = try sema.checkIntOrVector(block, operand, operand_src);
20311 const target = sema.mod.getTarget();
20312 const bits = scalar_ty.intInfo(target).bits;
20822 const bits = scalar_ty.intInfo(mod).bits;
2031320823 if (bits % 8 != 0) {
2031420824 return sema.fail(
2031520825 block,
2031620826 operand_src,
2031720827 "@byteSwap requires the number of bits to be evenly divisible by 8, but {} has {} bits",
20318 .{ scalar_ty.fmt(sema.mod), bits },
20828 .{ scalar_ty.fmt(mod), bits },
2031920829 );
2032020830 }
2032120831
......@@ -20323,11 +20833,11 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2032320833 return sema.addConstant(operand_ty, val);
2032420834 }
2032520835
20326 switch (operand_ty.zigTypeTag()) {
20836 switch (operand_ty.zigTypeTag(mod)) {
2032720837 .Int => {
2032820838 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20329 if (val.isUndef()) return sema.addConstUndef(operand_ty);
20330 const result_val = try val.byteSwap(operand_ty, target, sema.arena);
20839 if (val.isUndef(mod)) return sema.addConstUndef(operand_ty);
20840 const result_val = try val.byteSwap(operand_ty, mod, sema.arena);
2033120841 return sema.addConstant(operand_ty, result_val);
2033220842 } else operand_src;
2033320843
......@@ -20336,20 +20846,19 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
2033620846 },
2033720847 .Vector => {
2033820848 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20339 if (val.isUndef())
20849 if (val.isUndef(mod))
2034020850 return sema.addConstUndef(operand_ty);
2034120851
20342 const vec_len = operand_ty.vectorLen();
20343 var elem_buf: Value.ElemValueBuffer = undefined;
20344 const elems = try sema.arena.alloc(Value, vec_len);
20852 const vec_len = operand_ty.vectorLen(mod);
20853 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
2034520854 for (elems, 0..) |*elem, i| {
20346 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);
20347 elem.* = try elem_val.byteSwap(operand_ty, target, sema.arena);
20855 const elem_val = try val.elemValue(mod, i);
20856 elem.* = try (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod);
2034820857 }
20349 return sema.addConstant(
20350 operand_ty,
20351 try Value.Tag.aggregate.create(sema.arena, elems),
20352 );
20858 return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{
20859 .ty = operand_ty.toIntern(),
20860 .storage = .{ .elems = elems },
20861 } })).toValue());
2035320862 } else operand_src;
2035420863
2035520864 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -20371,12 +20880,12 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2037120880 return sema.addConstant(operand_ty, val);
2037220881 }
2037320882
20374 const target = sema.mod.getTarget();
20375 switch (operand_ty.zigTypeTag()) {
20883 const mod = sema.mod;
20884 switch (operand_ty.zigTypeTag(mod)) {
2037620885 .Int => {
2037720886 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20378 if (val.isUndef()) return sema.addConstUndef(operand_ty);
20379 const result_val = try val.bitReverse(operand_ty, target, sema.arena);
20887 if (val.isUndef(mod)) return sema.addConstUndef(operand_ty);
20888 const result_val = try val.bitReverse(operand_ty, mod, sema.arena);
2038020889 return sema.addConstant(operand_ty, result_val);
2038120890 } else operand_src;
2038220891
......@@ -20385,20 +20894,19 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2038520894 },
2038620895 .Vector => {
2038720896 const runtime_src = if (try sema.resolveMaybeUndefVal(operand)) |val| {
20388 if (val.isUndef())
20897 if (val.isUndef(mod))
2038920898 return sema.addConstUndef(operand_ty);
2039020899
20391 const vec_len = operand_ty.vectorLen();
20392 var elem_buf: Value.ElemValueBuffer = undefined;
20393 const elems = try sema.arena.alloc(Value, vec_len);
20900 const vec_len = operand_ty.vectorLen(mod);
20901 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
2039420902 for (elems, 0..) |*elem, i| {
20395 const elem_val = val.elemValueBuffer(sema.mod, i, &elem_buf);
20396 elem.* = try elem_val.bitReverse(scalar_ty, target, sema.arena);
20903 const elem_val = try val.elemValue(mod, i);
20904 elem.* = try (try elem_val.bitReverse(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod);
2039720905 }
20398 return sema.addConstant(
20399 operand_ty,
20400 try Value.Tag.aggregate.create(sema.arena, elems),
20401 );
20906 return sema.addConstant(operand_ty, (try mod.intern(.{ .aggregate = .{
20907 .ty = operand_ty.toIntern(),
20908 .storage = .{ .elems = elems },
20909 } })).toValue());
2040220910 } else operand_src;
2040320911
2040420912 try sema.requireRuntimeBlock(block, src, runtime_src);
......@@ -20428,15 +20936,15 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2042820936 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2042920937
2043020938 const ty = try sema.resolveType(block, lhs_src, extra.lhs);
20431 const field_name = try sema.resolveConstString(block, rhs_src, extra.rhs, "name of field must be comptime-known");
20432 const target = sema.mod.getTarget();
20939 const field_name = try sema.resolveConstStringIntern(block, rhs_src, extra.rhs, "name of field must be comptime-known");
2043320940
20941 const mod = sema.mod;
2043420942 try sema.resolveTypeLayout(ty);
20435 switch (ty.zigTypeTag()) {
20943 switch (ty.zigTypeTag(mod)) {
2043620944 .Struct => {},
2043720945 else => {
2043820946 const msg = msg: {
20439 const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)});
20947 const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(mod)});
2044020948 errdefer msg.destroy(sema.gpa);
2044120949 try sema.addDeclaredHereNote(msg, ty);
2044220950 break :msg msg;
......@@ -20445,45 +20953,47 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
2044520953 },
2044620954 }
2044720955
20448 const field_index = if (ty.isTuple()) blk: {
20449 if (mem.eql(u8, field_name, "len")) {
20956 const field_index = if (ty.isTuple(mod)) blk: {
20957 if (mod.intern_pool.stringEqlSlice(field_name, "len")) {
2045020958 return sema.fail(block, src, "no offset available for 'len' field of tuple", .{});
2045120959 }
2045220960 break :blk try sema.tupleFieldIndex(block, ty, field_name, rhs_src);
2045320961 } else try sema.structFieldIndex(block, ty, field_name, rhs_src);
2045420962
20455 if (ty.structFieldIsComptime(field_index)) {
20963 if (ty.structFieldIsComptime(field_index, mod)) {
2045620964 return sema.fail(block, src, "no offset available for comptime field", .{});
2045720965 }
2045820966
20459 switch (ty.containerLayout()) {
20967 switch (ty.containerLayout(mod)) {
2046020968 .Packed => {
2046120969 var bit_sum: u64 = 0;
20462 const fields = ty.structFields();
20970 const fields = ty.structFields(mod);
2046320971 for (fields.values(), 0..) |field, i| {
2046420972 if (i == field_index) {
2046520973 return bit_sum;
2046620974 }
20467 bit_sum += field.ty.bitSize(target);
20975 bit_sum += field.ty.bitSize(mod);
2046820976 } else unreachable;
2046920977 },
20470 else => return ty.structFieldOffset(field_index, target) * 8,
20978 else => return ty.structFieldOffset(field_index, mod) * 8,
2047120979 }
2047220980}
2047320981
2047420982fn checkNamespaceType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
20475 switch (ty.zigTypeTag()) {
20983 const mod = sema.mod;
20984 switch (ty.zigTypeTag(mod)) {
2047620985 .Struct, .Enum, .Union, .Opaque => return,
20477 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(sema.mod)}),
20986 else => return sema.fail(block, src, "expected struct, enum, union, or opaque; found '{}'", .{ty.fmt(mod)}),
2047820987 }
2047920988}
2048020989
2048120990/// Returns `true` if the type was a comptime_int.
2048220991fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool {
20483 switch (try ty.zigTypeTagOrPoison()) {
20992 const mod = sema.mod;
20993 switch (try ty.zigTypeTagOrPoison(mod)) {
2048420994 .ComptimeInt => return true,
2048520995 .Int => return false,
20486 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(sema.mod)}),
20996 else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty.fmt(mod)}),
2048720997 }
2048820998}
2048920999
......@@ -20493,8 +21003,9 @@ fn checkInvalidPtrArithmetic(
2049321003 src: LazySrcLoc,
2049421004 ty: Type,
2049521005) CompileError!void {
20496 switch (try ty.zigTypeTagOrPoison()) {
20497 .Pointer => switch (ty.ptrSize()) {
21006 const mod = sema.mod;
21007 switch (try ty.zigTypeTagOrPoison(mod)) {
21008 .Pointer => switch (ty.ptrSize(mod)) {
2049821009 .One, .Slice => return,
2049921010 .Many, .C => return sema.fail(
2050021011 block,
......@@ -20532,7 +21043,8 @@ fn checkPtrOperand(
2053221043 ty_src: LazySrcLoc,
2053321044 ty: Type,
2053421045) CompileError!void {
20535 switch (ty.zigTypeTag()) {
21046 const mod = sema.mod;
21047 switch (ty.zigTypeTag(mod)) {
2053621048 .Pointer => return,
2053721049 .Fn => {
2053821050 const msg = msg: {
......@@ -20540,7 +21052,7 @@ fn checkPtrOperand(
2054021052 block,
2054121053 ty_src,
2054221054 "expected pointer, found '{}'",
20543 .{ty.fmt(sema.mod)},
21055 .{ty.fmt(mod)},
2054421056 );
2054521057 errdefer msg.destroy(sema.gpa);
2054621058
......@@ -20550,10 +21062,10 @@ fn checkPtrOperand(
2055021062 };
2055121063 return sema.failWithOwnedErrorMsg(msg);
2055221064 },
20553 .Optional => if (ty.isPtrLikeOptional()) return,
21065 .Optional => if (ty.isPtrLikeOptional(mod)) return,
2055421066 else => {},
2055521067 }
20556 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)});
21068 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)});
2055721069}
2055821070
2055921071fn checkPtrType(
......@@ -20562,7 +21074,8 @@ fn checkPtrType(
2056221074 ty_src: LazySrcLoc,
2056321075 ty: Type,
2056421076) CompileError!void {
20565 switch (ty.zigTypeTag()) {
21077 const mod = sema.mod;
21078 switch (ty.zigTypeTag(mod)) {
2056621079 .Pointer => return,
2056721080 .Fn => {
2056821081 const msg = msg: {
......@@ -20570,7 +21083,7 @@ fn checkPtrType(
2057021083 block,
2057121084 ty_src,
2057221085 "expected pointer type, found '{}'",
20573 .{ty.fmt(sema.mod)},
21086 .{ty.fmt(mod)},
2057421087 );
2057521088 errdefer msg.destroy(sema.gpa);
2057621089
......@@ -20580,10 +21093,10 @@ fn checkPtrType(
2058021093 };
2058121094 return sema.failWithOwnedErrorMsg(msg);
2058221095 },
20583 .Optional => if (ty.isPtrLikeOptional()) return,
21096 .Optional => if (ty.isPtrLikeOptional(mod)) return,
2058421097 else => {},
2058521098 }
20586 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)});
21099 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(mod)});
2058721100}
2058821101
2058921102fn checkVectorElemType(
......@@ -20592,11 +21105,12 @@ fn checkVectorElemType(
2059221105 ty_src: LazySrcLoc,
2059321106 ty: Type,
2059421107) CompileError!void {
20595 switch (ty.zigTypeTag()) {
21108 const mod = sema.mod;
21109 switch (ty.zigTypeTag(mod)) {
2059621110 .Int, .Float, .Bool => return,
20597 else => if (ty.isPtrAtRuntime()) return,
21111 else => if (ty.isPtrAtRuntime(mod)) return,
2059821112 }
20599 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(sema.mod)});
21113 return sema.fail(block, ty_src, "expected integer, float, bool, or pointer for the vector element type; found '{}'", .{ty.fmt(mod)});
2060021114}
2060121115
2060221116fn checkFloatType(
......@@ -20605,9 +21119,10 @@ fn checkFloatType(
2060521119 ty_src: LazySrcLoc,
2060621120 ty: Type,
2060721121) CompileError!void {
20608 switch (ty.zigTypeTag()) {
21122 const mod = sema.mod;
21123 switch (ty.zigTypeTag(mod)) {
2060921124 .ComptimeInt, .ComptimeFloat, .Float => {},
20610 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(sema.mod)}),
21125 else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ty.fmt(mod)}),
2061121126 }
2061221127}
2061321128
......@@ -20617,13 +21132,14 @@ fn checkNumericType(
2061721132 ty_src: LazySrcLoc,
2061821133 ty: Type,
2061921134) CompileError!void {
20620 switch (ty.zigTypeTag()) {
21135 const mod = sema.mod;
21136 switch (ty.zigTypeTag(mod)) {
2062121137 .ComptimeFloat, .Float, .ComptimeInt, .Int => {},
20622 .Vector => switch (ty.childType().zigTypeTag()) {
21138 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
2062321139 .ComptimeFloat, .Float, .ComptimeInt, .Int => {},
2062421140 else => |t| return sema.fail(block, ty_src, "expected number, found '{}'", .{t}),
2062521141 },
20626 else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(sema.mod)}),
21142 else => return sema.fail(block, ty_src, "expected number, found '{}'", .{ty.fmt(mod)}),
2062721143 }
2062821144}
2062921145
......@@ -20637,9 +21153,10 @@ fn checkAtomicPtrOperand(
2063721153 ptr_src: LazySrcLoc,
2063821154 ptr_const: bool,
2063921155) CompileError!Air.Inst.Ref {
20640 const target = sema.mod.getTarget();
20641 var diag: target_util.AtomicPtrAlignmentDiagnostics = .{};
20642 const alignment = target_util.atomicPtrAlignment(target, elem_ty, &diag) catch |err| switch (err) {
21156 const mod = sema.mod;
21157 var diag: Module.AtomicPtrAlignmentDiagnostics = .{};
21158 const alignment = mod.atomicPtrAlignment(elem_ty, &diag) catch |err| switch (err) {
21159 error.OutOfMemory => return error.OutOfMemory,
2064321160 error.FloatTooBig => return sema.fail(
2064421161 block,
2064521162 elem_ty_src,
......@@ -20656,7 +21173,7 @@ fn checkAtomicPtrOperand(
2065621173 block,
2065721174 elem_ty_src,
2065821175 "expected bool, integer, float, enum, or pointer type; found '{}'",
20659 .{elem_ty.fmt(sema.mod)},
21176 .{elem_ty.fmt(mod)},
2066021177 ),
2066121178 };
2066221179
......@@ -20668,10 +21185,10 @@ fn checkAtomicPtrOperand(
2066821185 };
2066921186
2067021187 const ptr_ty = sema.typeOf(ptr);
20671 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison()) {
20672 .Pointer => ptr_ty.ptrInfo().data,
21188 const ptr_data = switch (try ptr_ty.zigTypeTagOrPoison(mod)) {
21189 .Pointer => ptr_ty.ptrInfo(mod),
2067321190 else => {
20674 const wanted_ptr_ty = try Type.ptr(sema.arena, sema.mod, wanted_ptr_data);
21191 const wanted_ptr_ty = try Type.ptr(sema.arena, mod, wanted_ptr_data);
2067521192 _ = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
2067621193 unreachable;
2067721194 },
......@@ -20681,7 +21198,7 @@ fn checkAtomicPtrOperand(
2068121198 wanted_ptr_data.@"allowzero" = ptr_data.@"allowzero";
2068221199 wanted_ptr_data.@"volatile" = ptr_data.@"volatile";
2068321200
20684 const wanted_ptr_ty = try Type.ptr(sema.arena, sema.mod, wanted_ptr_data);
21201 const wanted_ptr_ty = try Type.ptr(sema.arena, mod, wanted_ptr_data);
2068521202 const casted_ptr = try sema.coerce(block, wanted_ptr_ty, ptr, ptr_src);
2068621203
2068721204 return casted_ptr;
......@@ -20695,7 +21212,7 @@ fn checkPtrIsNotComptimeMutable(
2069521212 operand_src: LazySrcLoc,
2069621213) CompileError!void {
2069721214 _ = operand_src;
20698 if (ptr_val.isComptimeMutablePtr()) {
21215 if (ptr_val.isComptimeMutablePtr(sema.mod)) {
2069921216 return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{});
2070021217 }
2070121218}
......@@ -20704,7 +21221,7 @@ fn checkComptimeVarStore(
2070421221 sema: *Sema,
2070521222 block: *Block,
2070621223 src: LazySrcLoc,
20707 decl_ref_mut: Value.Payload.DeclRefMut.Data,
21224 decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl,
2070821225) CompileError!void {
2070921226 if (@enumToInt(decl_ref_mut.runtime_index) < @enumToInt(block.runtime_index)) {
2071021227 if (block.runtime_cond) |cond_src| {
......@@ -20735,20 +21252,21 @@ fn checkIntOrVector(
2073521252 operand: Air.Inst.Ref,
2073621253 operand_src: LazySrcLoc,
2073721254) CompileError!Type {
21255 const mod = sema.mod;
2073821256 const operand_ty = sema.typeOf(operand);
20739 switch (try operand_ty.zigTypeTagOrPoison()) {
21257 switch (try operand_ty.zigTypeTagOrPoison(mod)) {
2074021258 .Int => return operand_ty,
2074121259 .Vector => {
20742 const elem_ty = operand_ty.childType();
20743 switch (try elem_ty.zigTypeTagOrPoison()) {
21260 const elem_ty = operand_ty.childType(mod);
21261 switch (try elem_ty.zigTypeTagOrPoison(mod)) {
2074421262 .Int => return elem_ty,
2074521263 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
20746 elem_ty.fmt(sema.mod),
21264 elem_ty.fmt(mod),
2074721265 }),
2074821266 }
2074921267 },
2075021268 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{
20751 operand_ty.fmt(sema.mod),
21269 operand_ty.fmt(mod),
2075221270 }),
2075321271 }
2075421272}
......@@ -20759,27 +21277,29 @@ fn checkIntOrVectorAllowComptime(
2075921277 operand_ty: Type,
2076021278 operand_src: LazySrcLoc,
2076121279) CompileError!Type {
20762 switch (try operand_ty.zigTypeTagOrPoison()) {
21280 const mod = sema.mod;
21281 switch (try operand_ty.zigTypeTagOrPoison(mod)) {
2076321282 .Int, .ComptimeInt => return operand_ty,
2076421283 .Vector => {
20765 const elem_ty = operand_ty.childType();
20766 switch (try elem_ty.zigTypeTagOrPoison()) {
21284 const elem_ty = operand_ty.childType(mod);
21285 switch (try elem_ty.zigTypeTagOrPoison(mod)) {
2076721286 .Int, .ComptimeInt => return elem_ty,
2076821287 else => return sema.fail(block, operand_src, "expected vector of integers; found vector of '{}'", .{
20769 elem_ty.fmt(sema.mod),
21288 elem_ty.fmt(mod),
2077021289 }),
2077121290 }
2077221291 },
2077321292 else => return sema.fail(block, operand_src, "expected integer or vector, found '{}'", .{
20774 operand_ty.fmt(sema.mod),
21293 operand_ty.fmt(mod),
2077521294 }),
2077621295 }
2077721296}
2077821297
2077921298fn checkErrorSetType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!void {
20780 switch (ty.zigTypeTag()) {
21299 const mod = sema.mod;
21300 switch (ty.zigTypeTag(mod)) {
2078121301 .ErrorSet => return,
20782 else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(sema.mod)}),
21302 else => return sema.fail(block, src, "expected error set type, found '{}'", .{ty.fmt(mod)}),
2078321303 }
2078421304}
2078521305
......@@ -20805,11 +21325,12 @@ fn checkSimdBinOp(
2080521325 lhs_src: LazySrcLoc,
2080621326 rhs_src: LazySrcLoc,
2080721327) CompileError!SimdBinOp {
21328 const mod = sema.mod;
2080821329 const lhs_ty = sema.typeOf(uncasted_lhs);
2080921330 const rhs_ty = sema.typeOf(uncasted_rhs);
2081021331
2081121332 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
20812 var vec_len: ?usize = if (lhs_ty.zigTypeTag() == .Vector) lhs_ty.vectorLen() else null;
21333 var vec_len: ?usize = if (lhs_ty.zigTypeTag(mod) == .Vector) lhs_ty.vectorLen(mod) else null;
2081321334 const result_ty = try sema.resolvePeerTypes(block, src, &.{ uncasted_lhs, uncasted_rhs }, .{
2081421335 .override = &[_]?LazySrcLoc{ lhs_src, rhs_src },
2081521336 });
......@@ -20823,7 +21344,7 @@ fn checkSimdBinOp(
2082321344 .lhs_val = try sema.resolveMaybeUndefVal(lhs),
2082421345 .rhs_val = try sema.resolveMaybeUndefVal(rhs),
2082521346 .result_ty = result_ty,
20826 .scalar_ty = result_ty.scalarType(),
21347 .scalar_ty = result_ty.scalarType(mod),
2082721348 };
2082821349}
2082921350
......@@ -20836,8 +21357,9 @@ fn checkVectorizableBinaryOperands(
2083621357 lhs_src: LazySrcLoc,
2083721358 rhs_src: LazySrcLoc,
2083821359) CompileError!void {
20839 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison();
20840 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison();
21360 const mod = sema.mod;
21361 const lhs_zig_ty_tag = try lhs_ty.zigTypeTagOrPoison(mod);
21362 const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(mod);
2084121363 if (lhs_zig_ty_tag != .Vector and rhs_zig_ty_tag != .Vector) return;
2084221364
2084321365 const lhs_is_vector = switch (lhs_zig_ty_tag) {
......@@ -20850,8 +21372,8 @@ fn checkVectorizableBinaryOperands(
2085021372 };
2085121373
2085221374 if (lhs_is_vector and rhs_is_vector) {
20853 const lhs_len = lhs_ty.arrayLen();
20854 const rhs_len = rhs_ty.arrayLen();
21375 const lhs_len = lhs_ty.arrayLen(mod);
21376 const rhs_len = rhs_ty.arrayLen(mod);
2085521377 if (lhs_len != rhs_len) {
2085621378 const msg = msg: {
2085721379 const msg = try sema.errMsg(block, src, "vector length mismatch", .{});
......@@ -20865,7 +21387,7 @@ fn checkVectorizableBinaryOperands(
2086521387 } else {
2086621388 const msg = msg: {
2086721389 const msg = try sema.errMsg(block, src, "mixed scalar and vector operands: '{}' and '{}'", .{
20868 lhs_ty.fmt(sema.mod), rhs_ty.fmt(sema.mod),
21390 lhs_ty.fmt(mod), rhs_ty.fmt(mod),
2086921391 });
2087021392 errdefer msg.destroy(sema.gpa);
2087121393 if (lhs_is_vector) {
......@@ -20883,7 +21405,8 @@ fn checkVectorizableBinaryOperands(
2088321405
2088421406fn maybeOptionsSrc(sema: *Sema, block: *Block, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc {
2088521407 if (base_src == .unneeded) return .unneeded;
20886 return Module.optionsSrc(sema.gpa, sema.mod.declPtr(block.src_decl), base_src, wanted);
21408 const mod = sema.mod;
21409 return mod.optionsSrc(mod.declPtr(block.src_decl), base_src, wanted);
2088721410}
2088821411
2088921412fn resolveExportOptions(
......@@ -20891,7 +21414,10 @@ fn resolveExportOptions(
2089121414 block: *Block,
2089221415 src: LazySrcLoc,
2089321416 zir_ref: Zir.Inst.Ref,
20894) CompileError!std.builtin.ExportOptions {
21417) CompileError!Module.Export.Options {
21418 const mod = sema.mod;
21419 const gpa = sema.gpa;
21420 const ip = &mod.intern_pool;
2089521421 const export_options_ty = try sema.getBuiltinType("ExportOptions");
2089621422 const air_ref = try sema.resolveInst(zir_ref);
2089721423 const options = try sema.coerce(block, export_options_ty, air_ref, src);
......@@ -20901,26 +21427,26 @@ fn resolveExportOptions(
2090121427 const section_src = sema.maybeOptionsSrc(block, src, "section");
2090221428 const visibility_src = sema.maybeOptionsSrc(block, src, "visibility");
2090321429
20904 const name_operand = try sema.fieldVal(block, src, options, "name", name_src);
21430 const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src);
2090521431 const name_val = try sema.resolveConstValue(block, name_src, name_operand, "name of exported value must be comptime-known");
20906 const name_ty = Type.initTag(.const_slice_u8);
20907 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, sema.mod);
21432 const name_ty = Type.slice_const_u8;
21433 const name = try name_val.toAllocatedBytes(name_ty, sema.arena, mod);
2090821434
20909 const linkage_operand = try sema.fieldVal(block, src, options, "linkage", linkage_src);
21435 const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src);
2091021436 const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_operand, "linkage of exported value must be comptime-known");
20911 const linkage = linkage_val.toEnum(std.builtin.GlobalLinkage);
21437 const linkage = mod.toEnum(std.builtin.GlobalLinkage, linkage_val);
2091221438
20913 const section_operand = try sema.fieldVal(block, src, options, "section", section_src);
21439 const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "section"), section_src);
2091421440 const section_opt_val = try sema.resolveConstValue(block, section_src, section_operand, "linksection of exported value must be comptime-known");
20915 const section_ty = Type.initTag(.const_slice_u8);
20916 const section = if (section_opt_val.optionalValue()) |section_val|
20917 try section_val.toAllocatedBytes(section_ty, sema.arena, sema.mod)
21441 const section_ty = Type.slice_const_u8;
21442 const section = if (section_opt_val.optionalValue(mod)) |section_val|
21443 try section_val.toAllocatedBytes(section_ty, sema.arena, mod)
2091821444 else
2091921445 null;
2092021446
20921 const visibility_operand = try sema.fieldVal(block, src, options, "visibility", visibility_src);
21447 const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "visibility"), visibility_src);
2092221448 const visibility_val = try sema.resolveConstValue(block, visibility_src, visibility_operand, "visibility of exported value must be comptime-known");
20923 const visibility = visibility_val.toEnum(std.builtin.SymbolVisibility);
21449 const visibility = mod.toEnum(std.builtin.SymbolVisibility, visibility_val);
2092421450
2092521451 if (name.len < 1) {
2092621452 return sema.fail(block, name_src, "exported symbol name cannot be empty", .{});
......@@ -20932,10 +21458,10 @@ fn resolveExportOptions(
2093221458 });
2093321459 }
2093421460
20935 return std.builtin.ExportOptions{
20936 .name = name,
21461 return .{
21462 .name = try ip.getOrPutString(gpa, name),
2093721463 .linkage = linkage,
20938 .section = section,
21464 .section = try ip.getOrPutStringOpt(gpa, section),
2093921465 .visibility = visibility,
2094021466 };
2094121467}
......@@ -20948,11 +21474,12 @@ fn resolveBuiltinEnum(
2094821474 comptime name: []const u8,
2094921475 reason: []const u8,
2095021476) CompileError!@field(std.builtin, name) {
21477 const mod = sema.mod;
2095121478 const ty = try sema.getBuiltinType(name);
2095221479 const air_ref = try sema.resolveInst(zir_ref);
2095321480 const coerced = try sema.coerce(block, ty, air_ref, src);
2095421481 const val = try sema.resolveConstValue(block, src, coerced, reason);
20955 return val.toEnum(@field(std.builtin, name));
21482 return mod.toEnum(@field(std.builtin, name), val);
2095621483}
2095721484
2095821485fn resolveAtomicOrder(
......@@ -20979,6 +21506,7 @@ fn zirCmpxchg(
2097921506 block: *Block,
2098021507 extended: Zir.Inst.Extended.InstData,
2098121508) CompileError!Air.Inst.Ref {
21509 const mod = sema.mod;
2098221510 const extra = sema.code.extraData(Zir.Inst.Cmpxchg, extended.operand).data;
2098321511 const air_tag: Air.Inst.Tag = switch (extended.small) {
2098421512 0 => .cmpxchg_weak,
......@@ -20996,12 +21524,12 @@ fn zirCmpxchg(
2099621524 // zig fmt: on
2099721525 const expected_value = try sema.resolveInst(extra.expected_value);
2099821526 const elem_ty = sema.typeOf(expected_value);
20999 if (elem_ty.zigTypeTag() == .Float) {
21527 if (elem_ty.zigTypeTag(mod) == .Float) {
2100021528 return sema.fail(
2100121529 block,
2100221530 elem_ty_src,
2100321531 "expected bool, integer, enum, or pointer type; found '{}'",
21004 .{elem_ty.fmt(sema.mod)},
21532 .{elem_ty.fmt(mod)},
2100521533 );
2100621534 }
2100721535 const uncasted_ptr = try sema.resolveInst(extra.ptr);
......@@ -21023,29 +21551,34 @@ fn zirCmpxchg(
2102321551 return sema.fail(block, failure_order_src, "failure atomic ordering must not be Release or AcqRel", .{});
2102421552 }
2102521553
21026 const result_ty = try Type.optional(sema.arena, elem_ty);
21554 const result_ty = try Type.optional(sema.arena, elem_ty, mod);
2102721555
2102821556 // special case zero bit types
2102921557 if ((try sema.typeHasOnePossibleValue(elem_ty)) != null) {
21030 return sema.addConstant(result_ty, Value.null);
21558 return sema.addConstant(result_ty, (try mod.intern(.{ .opt = .{
21559 .ty = result_ty.toIntern(),
21560 .val = .none,
21561 } })).toValue());
2103121562 }
2103221563
2103321564 const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
2103421565 if (try sema.resolveMaybeUndefVal(expected_value)) |expected_val| {
2103521566 if (try sema.resolveMaybeUndefVal(new_value)) |new_val| {
21036 if (expected_val.isUndef() or new_val.isUndef()) {
21567 if (expected_val.isUndef(mod) or new_val.isUndef(mod)) {
2103721568 // TODO: this should probably cause the memory stored at the pointer
2103821569 // to become undef as well
2103921570 return sema.addConstUndef(result_ty);
2104021571 }
2104121572 const ptr_ty = sema.typeOf(ptr);
2104221573 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
21043 const result_val = if (stored_val.eql(expected_val, elem_ty, sema.mod)) blk: {
21044 try sema.storePtr(block, src, ptr, new_value);
21045 break :blk Value.null;
21046 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);
21047
21048 return sema.addConstant(result_ty, result_val);
21574 const result_val = try mod.intern(.{ .opt = .{
21575 .ty = result_ty.toIntern(),
21576 .val = if (stored_val.eql(expected_val, elem_ty, mod)) blk: {
21577 try sema.storePtr(block, src, ptr, new_value);
21578 break :blk .none;
21579 } else stored_val.toIntern(),
21580 } });
21581 return sema.addConstant(result_ty, result_val.toValue());
2104921582 } else break :rs new_value_src;
2105021583 } else break :rs expected_src;
2105121584 } else ptr_src;
......@@ -21069,6 +21602,7 @@ fn zirCmpxchg(
2106921602}
2107021603
2107121604fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
21605 const mod = sema.mod;
2107221606 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2107321607 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2107421608 const len_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
......@@ -21077,17 +21611,13 @@ fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
2107721611 const scalar = try sema.resolveInst(extra.rhs);
2107821612 const scalar_ty = sema.typeOf(scalar);
2107921613 try sema.checkVectorElemType(block, scalar_src, scalar_ty);
21080 const vector_ty = try Type.Tag.vector.create(sema.arena, .{
21614 const vector_ty = try mod.vectorType(.{
2108121615 .len = len,
21082 .elem_type = scalar_ty,
21616 .child = scalar_ty.toIntern(),
2108321617 });
2108421618 if (try sema.resolveMaybeUndefVal(scalar)) |scalar_val| {
21085 if (scalar_val.isUndef()) return sema.addConstUndef(vector_ty);
21086
21087 return sema.addConstant(
21088 vector_ty,
21089 try Value.Tag.repeated.create(sema.arena, scalar_val),
21090 );
21619 if (scalar_val.isUndef(mod)) return sema.addConstUndef(vector_ty);
21620 return sema.addConstant(vector_ty, try sema.splat(vector_ty, scalar_val));
2109121621 }
2109221622
2109321623 try sema.requireRuntimeBlock(block, inst_data.src(), scalar_src);
......@@ -21102,31 +21632,31 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2110221632 const operation = try sema.resolveBuiltinEnum(block, op_src, extra.lhs, "ReduceOp", "@reduce operation must be comptime-known");
2110321633 const operand = try sema.resolveInst(extra.rhs);
2110421634 const operand_ty = sema.typeOf(operand);
21105 const target = sema.mod.getTarget();
21635 const mod = sema.mod;
2110621636
21107 if (operand_ty.zigTypeTag() != .Vector) {
21108 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(sema.mod)});
21637 if (operand_ty.zigTypeTag(mod) != .Vector) {
21638 return sema.fail(block, operand_src, "expected vector, found '{}'", .{operand_ty.fmt(mod)});
2110921639 }
2111021640
21111 const scalar_ty = operand_ty.childType();
21641 const scalar_ty = operand_ty.childType(mod);
2111221642
2111321643 // Type-check depending on operation.
2111421644 switch (operation) {
21115 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag()) {
21645 .And, .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) {
2111621646 .Int, .Bool => {},
2111721647 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or boolean operand; found '{}'", .{
21118 @tagName(operation), operand_ty.fmt(sema.mod),
21648 @tagName(operation), operand_ty.fmt(mod),
2111921649 }),
2112021650 },
21121 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag()) {
21651 .Min, .Max, .Add, .Mul => switch (scalar_ty.zigTypeTag(mod)) {
2112221652 .Int, .Float => {},
2112321653 else => return sema.fail(block, operand_src, "@reduce operation '{s}' requires integer or float operand; found '{}'", .{
21124 @tagName(operation), operand_ty.fmt(sema.mod),
21654 @tagName(operation), operand_ty.fmt(mod),
2112521655 }),
2112621656 },
2112721657 }
2112821658
21129 const vec_len = operand_ty.vectorLen();
21659 const vec_len = operand_ty.vectorLen(mod);
2113021660 if (vec_len == 0) {
2113121661 // TODO re-evaluate if we should introduce a "neutral value" for some operations,
2113221662 // e.g. zero for add and one for mul.
......@@ -21134,21 +21664,20 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2113421664 }
2113521665
2113621666 if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
21137 if (operand_val.isUndef()) return sema.addConstUndef(scalar_ty);
21667 if (operand_val.isUndef(mod)) return sema.addConstUndef(scalar_ty);
2113821668
21139 var accum: Value = try operand_val.elemValue(sema.mod, sema.arena, 0);
21140 var elem_buf: Value.ElemValueBuffer = undefined;
21669 var accum: Value = try operand_val.elemValue(mod, 0);
2114121670 var i: u32 = 1;
2114221671 while (i < vec_len) : (i += 1) {
21143 const elem_val = operand_val.elemValueBuffer(sema.mod, i, &elem_buf);
21672 const elem_val = try operand_val.elemValue(mod, i);
2114421673 switch (operation) {
21145 .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, sema.mod),
21146 .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, sema.mod),
21147 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, sema.mod),
21148 .Min => accum = accum.numberMin(elem_val, target),
21149 .Max => accum = accum.numberMax(elem_val, target),
21674 .And => accum = try accum.bitwiseAnd(elem_val, scalar_ty, sema.arena, mod),
21675 .Or => accum = try accum.bitwiseOr(elem_val, scalar_ty, sema.arena, mod),
21676 .Xor => accum = try accum.bitwiseXor(elem_val, scalar_ty, sema.arena, mod),
21677 .Min => accum = accum.numberMin(elem_val, mod),
21678 .Max => accum = accum.numberMax(elem_val, mod),
2115021679 .Add => accum = try sema.numberAddWrapScalar(accum, elem_val, scalar_ty),
21151 .Mul => accum = try accum.numberMulWrap(elem_val, scalar_ty, sema.arena, sema.mod),
21680 .Mul => accum = try accum.numberMulWrap(elem_val, scalar_ty, sema.arena, mod),
2115221681 }
2115321682 }
2115421683 return sema.addConstant(scalar_ty, accum);
......@@ -21165,6 +21694,7 @@ fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2116521694}
2116621695
2116721696fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
21697 const mod = sema.mod;
2116821698 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2116921699 const extra = sema.code.extraData(Zir.Inst.Shuffle, inst_data.payload_index).data;
2117021700 const elem_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
......@@ -21177,13 +21707,13 @@ fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
2117721707 var mask = try sema.resolveInst(extra.mask);
2117821708 var mask_ty = sema.typeOf(mask);
2117921709
21180 const mask_len = switch (sema.typeOf(mask).zigTypeTag()) {
21181 .Array, .Vector => sema.typeOf(mask).arrayLen(),
21710 const mask_len = switch (sema.typeOf(mask).zigTypeTag(mod)) {
21711 .Array, .Vector => sema.typeOf(mask).arrayLen(mod),
2118221712 else => return sema.fail(block, mask_src, "expected vector or array, found '{}'", .{sema.typeOf(mask).fmt(sema.mod)}),
2118321713 };
21184 mask_ty = try Type.Tag.vector.create(sema.arena, .{
21185 .len = mask_len,
21186 .elem_type = Type.i32,
21714 mask_ty = try mod.vectorType(.{
21715 .len = @intCast(u32, mask_len),
21716 .child = .i32_type,
2118721717 });
2118821718 mask = try sema.coerce(block, mask_ty, mask, mask_src);
2118921719 const mask_val = try sema.resolveConstMaybeUndefVal(block, mask_src, mask, "shuffle mask must be comptime-known");
......@@ -21200,27 +21730,28 @@ fn analyzeShuffle(
2120021730 mask: Value,
2120121731 mask_len: u32,
2120221732) CompileError!Air.Inst.Ref {
21733 const mod = sema.mod;
2120321734 const a_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = src_node };
2120421735 const b_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = src_node };
2120521736 const mask_src: LazySrcLoc = .{ .node_offset_builtin_call_arg3 = src_node };
2120621737 var a = a_arg;
2120721738 var b = b_arg;
2120821739
21209 const res_ty = try Type.Tag.vector.create(sema.arena, .{
21740 const res_ty = try mod.vectorType(.{
2121021741 .len = mask_len,
21211 .elem_type = elem_ty,
21742 .child = elem_ty.toIntern(),
2121221743 });
2121321744
21214 var maybe_a_len = switch (sema.typeOf(a).zigTypeTag()) {
21215 .Array, .Vector => sema.typeOf(a).arrayLen(),
21745 var maybe_a_len = switch (sema.typeOf(a).zigTypeTag(mod)) {
21746 .Array, .Vector => sema.typeOf(a).arrayLen(mod),
2121621747 .Undefined => null,
2121721748 else => return sema.fail(block, a_src, "expected vector or array with element type '{}', found '{}'", .{
2121821749 elem_ty.fmt(sema.mod),
2121921750 sema.typeOf(a).fmt(sema.mod),
2122021751 }),
2122121752 };
21222 var maybe_b_len = switch (sema.typeOf(b).zigTypeTag()) {
21223 .Array, .Vector => sema.typeOf(b).arrayLen(),
21753 var maybe_b_len = switch (sema.typeOf(b).zigTypeTag(mod)) {
21754 .Array, .Vector => sema.typeOf(b).arrayLen(mod),
2122421755 .Undefined => null,
2122521756 else => return sema.fail(block, b_src, "expected vector or array with element type '{}', found '{}'", .{
2122621757 elem_ty.fmt(sema.mod),
......@@ -21230,16 +21761,16 @@ fn analyzeShuffle(
2123021761 if (maybe_a_len == null and maybe_b_len == null) {
2123121762 return sema.addConstUndef(res_ty);
2123221763 }
21233 const a_len = maybe_a_len orelse maybe_b_len.?;
21234 const b_len = maybe_b_len orelse a_len;
21764 const a_len = @intCast(u32, maybe_a_len orelse maybe_b_len.?);
21765 const b_len = @intCast(u32, maybe_b_len orelse a_len);
2123521766
21236 const a_ty = try Type.Tag.vector.create(sema.arena, .{
21767 const a_ty = try mod.vectorType(.{
2123721768 .len = a_len,
21238 .elem_type = elem_ty,
21769 .child = elem_ty.toIntern(),
2123921770 });
21240 const b_ty = try Type.Tag.vector.create(sema.arena, .{
21771 const b_ty = try mod.vectorType(.{
2124121772 .len = b_len,
21242 .elem_type = elem_ty,
21773 .child = elem_ty.toIntern(),
2124321774 });
2124421775
2124521776 if (maybe_a_len == null) a = try sema.addConstUndef(a_ty) else a = try sema.coerce(block, a_ty, a, a_src);
......@@ -21250,12 +21781,10 @@ fn analyzeShuffle(
2125021781 .{ b_len, b_src, b_ty },
2125121782 };
2125221783
21253 var i: usize = 0;
21254 while (i < mask_len) : (i += 1) {
21255 var buf: Value.ElemValueBuffer = undefined;
21256 const elem = mask.elemValueBuffer(sema.mod, i, &buf);
21257 if (elem.isUndef()) continue;
21258 const int = elem.toSignedInt(sema.mod.getTarget());
21784 for (0..@intCast(usize, mask_len)) |i| {
21785 const elem = try mask.elemValue(sema.mod, i);
21786 if (elem.isUndef(mod)) continue;
21787 const int = elem.toSignedInt(mod);
2125921788 var unsigned: u32 = undefined;
2126021789 var chosen: u32 = undefined;
2126121790 if (int >= 0) {
......@@ -21287,26 +21816,21 @@ fn analyzeShuffle(
2128721816
2128821817 if (try sema.resolveMaybeUndefVal(a)) |a_val| {
2128921818 if (try sema.resolveMaybeUndefVal(b)) |b_val| {
21290 const values = try sema.arena.alloc(Value, mask_len);
21291
21292 i = 0;
21293 while (i < mask_len) : (i += 1) {
21294 var buf: Value.ElemValueBuffer = undefined;
21295 const mask_elem_val = mask.elemValueBuffer(sema.mod, i, &buf);
21296 if (mask_elem_val.isUndef()) {
21297 values[i] = Value.undef;
21819 const values = try sema.arena.alloc(InternPool.Index, mask_len);
21820 for (values, 0..) |*value, i| {
21821 const mask_elem_val = try mask.elemValue(sema.mod, i);
21822 if (mask_elem_val.isUndef(mod)) {
21823 value.* = try mod.intern(.{ .undef = elem_ty.toIntern() });
2129821824 continue;
2129921825 }
21300 const int = mask_elem_val.toSignedInt(sema.mod.getTarget());
21826 const int = mask_elem_val.toSignedInt(mod);
2130121827 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int);
21302 if (int >= 0) {
21303 values[i] = try a_val.elemValue(sema.mod, sema.arena, unsigned);
21304 } else {
21305 values[i] = try b_val.elemValue(sema.mod, sema.arena, unsigned);
21306 }
21828 values[i] = try (try (if (int >= 0) a_val else b_val).elemValue(mod, unsigned)).intern(elem_ty, mod);
2130721829 }
21308 const res_val = try Value.Tag.aggregate.create(sema.arena, values);
21309 return sema.addConstant(res_ty, res_val);
21830 return sema.addConstant(res_ty, (try mod.intern(.{ .aggregate = .{
21831 .ty = res_ty.toIntern(),
21832 .storage = .{ .elems = values },
21833 } })).toValue());
2131021834 }
2131121835 }
2131221836
......@@ -21320,27 +21844,27 @@ fn analyzeShuffle(
2132021844 const max_src = if (a_len > b_len) a_src else b_src;
2132121845 const max_len = try sema.usizeCast(block, max_src, std.math.max(a_len, b_len));
2132221846
21323 const expand_mask_values = try sema.arena.alloc(Value, max_len);
21324 i = 0;
21325 while (i < min_len) : (i += 1) {
21326 expand_mask_values[i] = try Value.Tag.int_u64.create(sema.arena, i);
21847 const expand_mask_values = try sema.arena.alloc(InternPool.Index, max_len);
21848 for (@intCast(usize, 0)..@intCast(usize, min_len)) |i| {
21849 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, i)).toIntern();
2132721850 }
21328 while (i < max_len) : (i += 1) {
21329 expand_mask_values[i] = Value.negative_one;
21851 for (@intCast(usize, min_len)..@intCast(usize, max_len)) |i| {
21852 expand_mask_values[i] = (try mod.intValue(Type.comptime_int, -1)).toIntern();
2133021853 }
21331 const expand_mask = try Value.Tag.aggregate.create(sema.arena, expand_mask_values);
21854 const expand_mask = try mod.intern(.{ .aggregate = .{
21855 .ty = (try mod.vectorType(.{ .len = @intCast(u32, max_len), .child = .comptime_int_type })).toIntern(),
21856 .storage = .{ .elems = expand_mask_values },
21857 } });
2133221858
2133321859 if (a_len < b_len) {
2133421860 const undef = try sema.addConstUndef(a_ty);
21335 a = try sema.analyzeShuffle(block, src_node, elem_ty, a, undef, expand_mask, @intCast(u32, max_len));
21861 a = try sema.analyzeShuffle(block, src_node, elem_ty, a, undef, expand_mask.toValue(), @intCast(u32, max_len));
2133621862 } else {
2133721863 const undef = try sema.addConstUndef(b_ty);
21338 b = try sema.analyzeShuffle(block, src_node, elem_ty, b, undef, expand_mask, @intCast(u32, max_len));
21864 b = try sema.analyzeShuffle(block, src_node, elem_ty, b, undef, expand_mask.toValue(), @intCast(u32, max_len));
2133921865 }
2134021866 }
2134121867
21342 const mask_index = @intCast(u32, sema.air_values.items.len);
21343 try sema.air_values.append(sema.gpa, mask);
2134421868 return block.addInst(.{
2134521869 .tag = .shuffle,
2134621870 .data = .{ .ty_pl = .{
......@@ -21348,7 +21872,7 @@ fn analyzeShuffle(
2134821872 .payload = try block.sema.addExtra(Air.Shuffle{
2134921873 .a = a,
2135021874 .b = b,
21351 .mask = mask_index,
21875 .mask = mask.toIntern(),
2135221876 .mask_len = mask_len,
2135321877 }),
2135421878 } },
......@@ -21356,6 +21880,7 @@ fn analyzeShuffle(
2135621880}
2135721881
2135821882fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref {
21883 const mod = sema.mod;
2135921884 const extra = sema.code.extraData(Zir.Inst.Select, extended.operand).data;
2136021885
2136121886 const src = LazySrcLoc.nodeOffset(extra.node);
......@@ -21369,16 +21894,22 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2136921894 const pred_uncoerced = try sema.resolveInst(extra.pred);
2137021895 const pred_ty = sema.typeOf(pred_uncoerced);
2137121896
21372 const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison()) {
21373 .Vector, .Array => pred_ty.arrayLen(),
21374 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(sema.mod)}),
21897 const vec_len_u64 = switch (try pred_ty.zigTypeTagOrPoison(mod)) {
21898 .Vector, .Array => pred_ty.arrayLen(mod),
21899 else => return sema.fail(block, pred_src, "expected vector or array, found '{}'", .{pred_ty.fmt(mod)}),
2137521900 };
21376 const vec_len = try sema.usizeCast(block, pred_src, vec_len_u64);
21901 const vec_len = @intCast(u32, try sema.usizeCast(block, pred_src, vec_len_u64));
2137721902
21378 const bool_vec_ty = try Type.vector(sema.arena, vec_len, Type.bool);
21903 const bool_vec_ty = try mod.vectorType(.{
21904 .len = vec_len,
21905 .child = .bool_type,
21906 });
2137921907 const pred = try sema.coerce(block, bool_vec_ty, pred_uncoerced, pred_src);
2138021908
21381 const vec_ty = try Type.vector(sema.arena, vec_len, elem_ty);
21909 const vec_ty = try mod.vectorType(.{
21910 .len = vec_len,
21911 .child = elem_ty.toIntern(),
21912 });
2138221913 const a = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.a), a_src);
2138321914 const b = try sema.coerce(block, vec_ty, try sema.resolveInst(extra.b), b_src);
2138421915
......@@ -21387,45 +21918,40 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C
2138721918 const maybe_b = try sema.resolveMaybeUndefVal(b);
2138821919
2138921920 const runtime_src = if (maybe_pred) |pred_val| rs: {
21390 if (pred_val.isUndef()) return sema.addConstUndef(vec_ty);
21921 if (pred_val.isUndef(mod)) return sema.addConstUndef(vec_ty);
2139121922
2139221923 if (maybe_a) |a_val| {
21393 if (a_val.isUndef()) return sema.addConstUndef(vec_ty);
21924 if (a_val.isUndef(mod)) return sema.addConstUndef(vec_ty);
2139421925
2139521926 if (maybe_b) |b_val| {
21396 if (b_val.isUndef()) return sema.addConstUndef(vec_ty);
21927 if (b_val.isUndef(mod)) return sema.addConstUndef(vec_ty);
2139721928
21398 var buf: Value.ElemValueBuffer = undefined;
21399 const elems = try sema.gpa.alloc(Value, vec_len);
21929 const elems = try sema.gpa.alloc(InternPool.Index, vec_len);
2140021930 for (elems, 0..) |*elem, i| {
21401 const pred_elem_val = pred_val.elemValueBuffer(sema.mod, i, &buf);
21931 const pred_elem_val = try pred_val.elemValue(mod, i);
2140221932 const should_choose_a = pred_elem_val.toBool();
21403 if (should_choose_a) {
21404 elem.* = a_val.elemValueBuffer(sema.mod, i, &buf);
21405 } else {
21406 elem.* = b_val.elemValueBuffer(sema.mod, i, &buf);
21407 }
21933 elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod);
2140821934 }
2140921935
21410 return sema.addConstant(
21411 vec_ty,
21412 try Value.Tag.aggregate.create(sema.arena, elems),
21413 );
21936 return sema.addConstant(vec_ty, (try mod.intern(.{ .aggregate = .{
21937 .ty = vec_ty.toIntern(),
21938 .storage = .{ .elems = elems },
21939 } })).toValue());
2141421940 } else {
2141521941 break :rs b_src;
2141621942 }
2141721943 } else {
2141821944 if (maybe_b) |b_val| {
21419 if (b_val.isUndef()) return sema.addConstUndef(vec_ty);
21945 if (b_val.isUndef(mod)) return sema.addConstUndef(vec_ty);
2142021946 }
2142121947 break :rs a_src;
2142221948 }
2142321949 } else rs: {
2142421950 if (maybe_a) |a_val| {
21425 if (a_val.isUndef()) return sema.addConstUndef(vec_ty);
21951 if (a_val.isUndef(mod)) return sema.addConstUndef(vec_ty);
2142621952 }
2142721953 if (maybe_b) |b_val| {
21428 if (b_val.isUndef()) return sema.addConstUndef(vec_ty);
21954 if (b_val.isUndef(mod)) return sema.addConstUndef(vec_ty);
2142921955 }
2143021956 break :rs pred_src;
2143121957 };
......@@ -21489,6 +22015,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
2148922015}
2149022016
2149122017fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
22018 const mod = sema.mod;
2149222019 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2149322020 const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data;
2149422021 const src = inst_data.src();
......@@ -21505,7 +22032,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2150522032 const ptr = try sema.checkAtomicPtrOperand(block, elem_ty, elem_ty_src, uncasted_ptr, ptr_src, false);
2150622033 const op = try sema.resolveAtomicRmwOp(block, op_src, extra.operation);
2150722034
21508 switch (elem_ty.zigTypeTag()) {
22035 switch (elem_ty.zigTypeTag(mod)) {
2150922036 .Enum => if (op != .Xchg) {
2151022037 return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{});
2151122038 },
......@@ -21535,8 +22062,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2153522062 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
2153622063 break :rs operand_src;
2153722064 };
21538 if (ptr_val.isComptimeMutablePtr()) {
21539 const target = sema.mod.getTarget();
22065 if (ptr_val.isComptimeMutablePtr(mod)) {
2154022066 const ptr_ty = sema.typeOf(ptr);
2154122067 const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src;
2154222068 const new_val = switch (op) {
......@@ -21544,12 +22070,12 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2154422070 .Xchg => operand_val,
2154522071 .Add => try sema.numberAddWrapScalar(stored_val, operand_val, elem_ty),
2154622072 .Sub => try sema.numberSubWrapScalar(stored_val, operand_val, elem_ty),
21547 .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, sema.mod),
21548 .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, sema.mod),
21549 .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, sema.mod),
21550 .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, sema.mod),
21551 .Max => stored_val.numberMax (operand_val, target),
21552 .Min => stored_val.numberMin (operand_val, target),
22073 .And => try stored_val.bitwiseAnd (operand_val, elem_ty, sema.arena, mod),
22074 .Nand => try stored_val.bitwiseNand (operand_val, elem_ty, sema.arena, mod),
22075 .Or => try stored_val.bitwiseOr (operand_val, elem_ty, sema.arena, mod),
22076 .Xor => try stored_val.bitwiseXor (operand_val, elem_ty, sema.arena, mod),
22077 .Max => stored_val.numberMax (operand_val, mod),
22078 .Min => stored_val.numberMin (operand_val, mod),
2155322079 // zig fmt: on
2155422080 };
2155522081 try sema.storePtrVal(block, src, ptr_val, new_val, elem_ty);
......@@ -21623,18 +22149,19 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2162322149 const maybe_mulend1 = try sema.resolveMaybeUndefVal(mulend1);
2162422150 const maybe_mulend2 = try sema.resolveMaybeUndefVal(mulend2);
2162522151 const maybe_addend = try sema.resolveMaybeUndefVal(addend);
22152 const mod = sema.mod;
2162622153
21627 switch (ty.zigTypeTag()) {
22154 switch (ty.zigTypeTag(mod)) {
2162822155 .ComptimeFloat, .Float, .Vector => {},
2162922156 else => return sema.fail(block, src, "expected vector of floats or float type, found '{}'", .{ty.fmt(sema.mod)}),
2163022157 }
2163122158
2163222159 const runtime_src = if (maybe_mulend1) |mulend1_val| rs: {
2163322160 if (maybe_mulend2) |mulend2_val| {
21634 if (mulend2_val.isUndef()) return sema.addConstUndef(ty);
22161 if (mulend2_val.isUndef(mod)) return sema.addConstUndef(ty);
2163522162
2163622163 if (maybe_addend) |addend_val| {
21637 if (addend_val.isUndef()) return sema.addConstUndef(ty);
22164 if (addend_val.isUndef(mod)) return sema.addConstUndef(ty);
2163822165 const result_val = try Value.mulAdd(ty, mulend1_val, mulend2_val, addend_val, sema.arena, sema.mod);
2163922166 return sema.addConstant(ty, result_val);
2164022167 } else {
......@@ -21642,16 +22169,16 @@ fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
2164222169 }
2164322170 } else {
2164422171 if (maybe_addend) |addend_val| {
21645 if (addend_val.isUndef()) return sema.addConstUndef(ty);
22172 if (addend_val.isUndef(mod)) return sema.addConstUndef(ty);
2164622173 }
2164722174 break :rs mulend2_src;
2164822175 }
2164922176 } else rs: {
2165022177 if (maybe_mulend2) |mulend2_val| {
21651 if (mulend2_val.isUndef()) return sema.addConstUndef(ty);
22178 if (mulend2_val.isUndef(mod)) return sema.addConstUndef(ty);
2165222179 }
2165322180 if (maybe_addend) |addend_val| {
21654 if (addend_val.isUndef()) return sema.addConstUndef(ty);
22181 if (addend_val.isUndef(mod)) return sema.addConstUndef(ty);
2165522182 }
2165622183 break :rs mulend1_src;
2165722184 };
......@@ -21673,6 +22200,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2167322200 const tracy = trace(@src());
2167422201 defer tracy.end();
2167522202
22203 const mod = sema.mod;
2167622204 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2167722205 const modifier_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
2167822206 const func_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
......@@ -21686,7 +22214,7 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2168622214 const air_ref = try sema.resolveInst(extra.modifier);
2168722215 const modifier_ref = try sema.coerce(block, modifier_ty, air_ref, modifier_src);
2168822216 const modifier_val = try sema.resolveConstValue(block, modifier_src, modifier_ref, "call modifier must be comptime-known");
21689 var modifier = modifier_val.toEnum(std.builtin.CallModifier);
22217 var modifier = mod.toEnum(std.builtin.CallModifier, modifier_val);
2169022218 switch (modifier) {
2169122219 // These can be upgraded to comptime or nosuspend calls.
2169222220 .auto, .never_tail, .no_async => {
......@@ -21732,18 +22260,17 @@ fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
2173222260 const args = try sema.resolveInst(extra.args);
2173322261
2173422262 const args_ty = sema.typeOf(args);
21735 if (!args_ty.isTuple() and args_ty.tag() != .empty_struct_literal) {
22263 if (!args_ty.isTuple(mod) and args_ty.toIntern() != .empty_struct_type) {
2173622264 return sema.fail(block, args_src, "expected a tuple, found '{}'", .{args_ty.fmt(sema.mod)});
2173722265 }
2173822266
21739 var resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount());
22267 var resolved_args: []Air.Inst.Ref = try sema.arena.alloc(Air.Inst.Ref, args_ty.structFieldCount(mod));
2174022268 for (resolved_args, 0..) |*resolved, i| {
2174122269 resolved.* = try sema.tupleFieldValByIndex(block, args_src, args, @intCast(u32, i), args_ty);
2174222270 }
2174322271
2174422272 const callee_ty = sema.typeOf(func);
2174522273 const func_ty = try sema.checkCallArgumentCount(block, func, func_src, callee_ty, resolved_args.len, false);
21746
2174722274 const ensure_result_used = extra.flags.ensure_result_used;
2174822275 return sema.analyzeCall(block, func, func_ty, func_src, call_src, modifier, ensure_result_used, resolved_args, null, null);
2174922276}
......@@ -21757,19 +22284,21 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2175722284 const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
2175822285
2175922286 const parent_ty = try sema.resolveType(block, ty_src, extra.parent_type);
21760 const field_name = try sema.resolveConstString(block, name_src, extra.field_name, "field name must be comptime-known");
22287 const field_name = try sema.resolveConstStringIntern(block, name_src, extra.field_name, "field name must be comptime-known");
2176122288 const field_ptr = try sema.resolveInst(extra.field_ptr);
2176222289 const field_ptr_ty = sema.typeOf(field_ptr);
22290 const mod = sema.mod;
22291 const ip = &mod.intern_pool;
2176322292
21764 if (parent_ty.zigTypeTag() != .Struct and parent_ty.zigTypeTag() != .Union) {
22293 if (parent_ty.zigTypeTag(mod) != .Struct and parent_ty.zigTypeTag(mod) != .Union) {
2176522294 return sema.fail(block, ty_src, "expected struct or union type, found '{}'", .{parent_ty.fmt(sema.mod)});
2176622295 }
2176722296 try sema.resolveTypeLayout(parent_ty);
2176822297
21769 const field_index = switch (parent_ty.zigTypeTag()) {
22298 const field_index = switch (parent_ty.zigTypeTag(mod)) {
2177022299 .Struct => blk: {
21771 if (parent_ty.isTuple()) {
21772 if (mem.eql(u8, field_name, "len")) {
22300 if (parent_ty.isTuple(mod)) {
22301 if (ip.stringEqlSlice(field_name, "len")) {
2177322302 return sema.fail(block, src, "cannot get @fieldParentPtr of 'len' field of tuple", .{});
2177422303 }
2177522304 break :blk try sema.tupleFieldIndex(block, parent_ty, field_name, name_src);
......@@ -21781,27 +22310,27 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2178122310 else => unreachable,
2178222311 };
2178322312
21784 if (parent_ty.zigTypeTag() == .Struct and parent_ty.structFieldIsComptime(field_index)) {
22313 if (parent_ty.zigTypeTag(mod) == .Struct and parent_ty.structFieldIsComptime(field_index, mod)) {
2178522314 return sema.fail(block, src, "cannot get @fieldParentPtr of a comptime field", .{});
2178622315 }
2178722316
2178822317 try sema.checkPtrOperand(block, ptr_src, field_ptr_ty);
21789 const field_ptr_ty_info = field_ptr_ty.ptrInfo().data;
22318 const field_ptr_ty_info = field_ptr_ty.ptrInfo(mod);
2179022319
2179122320 var ptr_ty_data: Type.Payload.Pointer.Data = .{
21792 .pointee_type = parent_ty.structFieldType(field_index),
22321 .pointee_type = parent_ty.structFieldType(field_index, mod),
2179322322 .mutable = field_ptr_ty_info.mutable,
2179422323 .@"addrspace" = field_ptr_ty_info.@"addrspace",
2179522324 };
2179622325
21797 if (parent_ty.containerLayout() == .Packed) {
22326 if (parent_ty.containerLayout(mod) == .Packed) {
2179822327 return sema.fail(block, src, "TODO handle packed structs/unions with @fieldParentPtr", .{});
2179922328 } else {
2180022329 ptr_ty_data.@"align" = blk: {
21801 if (parent_ty.castTag(.@"struct")) |struct_obj| {
21802 break :blk struct_obj.data.fields.values()[field_index].abi_align;
21803 } else if (parent_ty.cast(Type.Payload.Union)) |union_obj| {
21804 break :blk union_obj.data.fields.values()[field_index].abi_align;
22330 if (mod.typeToStruct(parent_ty)) |struct_obj| {
22331 break :blk struct_obj.fields.values()[field_index].abi_align;
22332 } else if (mod.typeToUnion(parent_ty)) |union_obj| {
22333 break :blk union_obj.fields.values()[field_index].abi_align;
2180522334 } else {
2180622335 break :blk 0;
2180722336 }
......@@ -21815,19 +22344,24 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2181522344 const result_ptr = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
2181622345
2181722346 if (try sema.resolveDefinedValue(block, src, casted_field_ptr)) |field_ptr_val| {
21818 const payload = field_ptr_val.castTag(.field_ptr) orelse {
21819 return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
21820 };
21821 if (payload.data.field_index != field_index) {
22347 const field = switch (ip.indexToKey(field_ptr_val.toIntern())) {
22348 .ptr => |ptr| switch (ptr.addr) {
22349 .field => |field| field,
22350 else => null,
22351 },
22352 else => null,
22353 } orelse return sema.fail(block, ptr_src, "pointer value not based on parent struct", .{});
22354
22355 if (field.index != field_index) {
2182222356 const msg = msg: {
2182322357 const msg = try sema.errMsg(
2182422358 block,
2182522359 src,
21826 "field '{s}' has index '{d}' but pointer value is index '{d}' of struct '{}'",
22360 "field '{}' has index '{d}' but pointer value is index '{d}' of struct '{}'",
2182722361 .{
21828 field_name,
22362 field_name.fmt(ip),
2182922363 field_index,
21830 payload.data.field_index,
22364 field.index,
2183122365 parent_ty.fmt(sema.mod),
2183222366 },
2183322367 );
......@@ -21837,7 +22371,7 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
2183722371 };
2183822372 return sema.failWithOwnedErrorMsg(msg);
2183922373 }
21840 return sema.addConstant(result_ptr, payload.data.container_ptr);
22374 return sema.addConstant(result_ptr, field.base.toValue());
2184122375 }
2184222376
2184322377 try sema.requireRuntimeBlock(block, src, ptr_src);
......@@ -21913,15 +22447,14 @@ fn analyzeMinMax(
2191322447) CompileError!Air.Inst.Ref {
2191422448 assert(operands.len == operand_srcs.len);
2191522449 assert(operands.len > 0);
22450 const mod = sema.mod;
2191622451
2191722452 if (operands.len == 1) return operands[0];
2191822453
21919 const mod = sema.mod;
21920 const target = mod.getTarget();
2192122454 const opFunc = switch (air_tag) {
2192222455 .min => Value.numberMin,
2192322456 .max => Value.numberMax,
21924 else => unreachable,
22457 else => @compileError("unreachable"),
2192522458 };
2192622459
2192722460 // First, find all comptime-known arguments, and get their min/max
......@@ -21939,32 +22472,30 @@ fn analyzeMinMax(
2193922472
2194022473 runtime_known.unset(operand_idx);
2194122474
21942 if (cur_val.isUndef()) continue; // result is also undef
21943 if (operand_val.isUndef()) {
22475 if (cur_val.isUndef(mod)) continue; // result is also undef
22476 if (operand_val.isUndef(mod)) {
2194422477 cur_minmax = try sema.addConstUndef(simd_op.result_ty);
2194522478 continue;
2194622479 }
2194722480
21948 try sema.resolveLazyValue(cur_val);
21949 try sema.resolveLazyValue(operand_val);
22481 const resolved_cur_val = try sema.resolveLazyValue(cur_val);
22482 const resolved_operand_val = try sema.resolveLazyValue(operand_val);
2195022483
2195122484 const vec_len = simd_op.len orelse {
21952 const result_val = opFunc(cur_val, operand_val, target);
22485 const result_val = opFunc(resolved_cur_val, resolved_operand_val, mod);
2195322486 cur_minmax = try sema.addConstant(simd_op.result_ty, result_val);
2195422487 continue;
2195522488 };
21956 var lhs_buf: Value.ElemValueBuffer = undefined;
21957 var rhs_buf: Value.ElemValueBuffer = undefined;
21958 const elems = try sema.arena.alloc(Value, vec_len);
22489 const elems = try sema.arena.alloc(InternPool.Index, vec_len);
2195922490 for (elems, 0..) |*elem, i| {
21960 const lhs_elem_val = cur_val.elemValueBuffer(mod, i, &lhs_buf);
21961 const rhs_elem_val = operand_val.elemValueBuffer(mod, i, &rhs_buf);
21962 elem.* = opFunc(lhs_elem_val, rhs_elem_val, target);
21963 }
21964 cur_minmax = try sema.addConstant(
21965 simd_op.result_ty,
21966 try Value.Tag.aggregate.create(sema.arena, elems),
21967 );
22491 const lhs_elem_val = try resolved_cur_val.elemValue(mod, i);
22492 const rhs_elem_val = try resolved_operand_val.elemValue(mod, i);
22493 elem.* = try opFunc(lhs_elem_val, rhs_elem_val, mod).intern(simd_op.scalar_ty, mod);
22494 }
22495 cur_minmax = try sema.addConstant(simd_op.result_ty, (try mod.intern(.{ .aggregate = .{
22496 .ty = simd_op.result_ty.toIntern(),
22497 .storage = .{ .elems = elems },
22498 } })).toValue());
2196822499 } else {
2196922500 runtime_known.unset(operand_idx);
2197022501 cur_minmax = try sema.addConstant(sema.typeOf(operand), uncasted_operand_val);
......@@ -21984,28 +22515,31 @@ fn analyzeMinMax(
2198422515 break :refined orig_ty;
2198522516 }
2198622517
21987 const refined_ty = if (orig_ty.zigTypeTag() == .Vector) blk: {
21988 const elem_ty = orig_ty.childType();
21989 const len = orig_ty.vectorLen();
22518 const refined_ty = if (orig_ty.zigTypeTag(mod) == .Vector) blk: {
22519 const elem_ty = orig_ty.childType(mod);
22520 const len = orig_ty.vectorLen(mod);
2199022521
2199122522 if (len == 0) break :blk orig_ty;
2199222523 if (elem_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats
2199322524
21994 var cur_min: Value = try val.elemValue(mod, sema.arena, 0);
22525 var cur_min: Value = try val.elemValue(mod, 0);
2199522526 var cur_max: Value = cur_min;
2199622527 for (1..len) |idx| {
21997 const elem_val = try val.elemValue(mod, sema.arena, idx);
21998 if (elem_val.isUndef()) break :blk orig_ty; // can't refine undef
21999 if (Value.order(elem_val, cur_min, target).compare(.lt)) cur_min = elem_val;
22000 if (Value.order(elem_val, cur_max, target).compare(.gt)) cur_max = elem_val;
22528 const elem_val = try val.elemValue(mod, idx);
22529 if (elem_val.isUndef(mod)) break :blk orig_ty; // can't refine undef
22530 if (Value.order(elem_val, cur_min, mod).compare(.lt)) cur_min = elem_val;
22531 if (Value.order(elem_val, cur_max, mod).compare(.gt)) cur_max = elem_val;
2200122532 }
2200222533
22003 const refined_elem_ty = try Type.intFittingRange(target, sema.arena, cur_min, cur_max);
22004 break :blk try Type.vector(sema.arena, len, refined_elem_ty);
22534 const refined_elem_ty = try mod.intFittingRange(cur_min, cur_max);
22535 break :blk try mod.vectorType(.{
22536 .len = len,
22537 .child = refined_elem_ty.toIntern(),
22538 });
2200522539 } else blk: {
2200622540 if (orig_ty.isAnyFloat()) break :blk orig_ty; // can't refine floats
22007 if (val.isUndef()) break :blk orig_ty; // can't refine undef
22008 break :blk try Type.intFittingRange(target, sema.arena, val, val);
22541 if (val.isUndef(mod)) break :blk orig_ty; // can't refine undef
22542 break :blk try mod.intFittingRange(val, val);
2200922543 };
2201022544
2201122545 // Apply the refined type to the current value - this isn't strictly necessary in the
......@@ -22016,7 +22550,7 @@ fn analyzeMinMax(
2201622550 if (std.debug.runtime_safety) {
2201722551 assert(try sema.intFitsInType(val, refined_ty, null));
2201822552 }
22019 cur_minmax = try sema.addConstant(refined_ty, val);
22553 cur_minmax = try sema.coerceInMemory(block, val, orig_ty, refined_ty, src);
2202022554 }
2202122555
2202222556 break :refined refined_ty;
......@@ -22032,7 +22566,7 @@ fn analyzeMinMax(
2203222566 // If the comptime-known part is undef we can avoid emitting actual instructions later
2203322567 const known_undef = if (cur_minmax) |operand| blk: {
2203422568 const val = (try sema.resolveMaybeUndefVal(operand)).?;
22035 break :blk val.isUndef();
22569 break :blk val.isUndef(mod);
2203622570 } else false;
2203722571
2203822572 if (cur_minmax == null) {
......@@ -22061,29 +22595,32 @@ fn analyzeMinMax(
2206122595 // Finally, refine the type based on the comptime-known bound.
2206222596 if (known_undef) break :refine; // can't refine undef
2206322597 const unrefined_ty = sema.typeOf(cur_minmax.?);
22064 const is_vector = unrefined_ty.zigTypeTag() == .Vector;
22065 const comptime_elem_ty = if (is_vector) comptime_ty.childType() else comptime_ty;
22066 const unrefined_elem_ty = if (is_vector) unrefined_ty.childType() else unrefined_ty;
22598 const is_vector = unrefined_ty.zigTypeTag(mod) == .Vector;
22599 const comptime_elem_ty = if (is_vector) comptime_ty.childType(mod) else comptime_ty;
22600 const unrefined_elem_ty = if (is_vector) unrefined_ty.childType(mod) else unrefined_ty;
2206722601
2206822602 if (unrefined_elem_ty.isAnyFloat()) break :refine; // we can't refine floats
2206922603
2207022604 // Compute the final bounds based on the runtime type and the comptime-known bound type
2207122605 const min_val = switch (air_tag) {
22072 .min => try unrefined_elem_ty.minInt(sema.arena, target),
22073 .max => try comptime_elem_ty.minInt(sema.arena, target), // @max(ct, rt) >= ct
22606 .min => try unrefined_elem_ty.minInt(mod, unrefined_elem_ty),
22607 .max => try comptime_elem_ty.minInt(mod, comptime_elem_ty), // @max(ct, rt) >= ct
2207422608 else => unreachable,
2207522609 };
2207622610 const max_val = switch (air_tag) {
22077 .min => try comptime_elem_ty.maxInt(sema.arena, target), // @min(ct, rt) <= ct
22078 .max => try unrefined_elem_ty.maxInt(sema.arena, target),
22611 .min => try comptime_elem_ty.maxInt(mod, comptime_elem_ty), // @min(ct, rt) <= ct
22612 .max => try unrefined_elem_ty.maxInt(mod, unrefined_elem_ty),
2207922613 else => unreachable,
2208022614 };
2208122615
2208222616 // Find the smallest type which can contain these bounds
22083 const final_elem_ty = try Type.intFittingRange(target, sema.arena, min_val, max_val);
22617 const final_elem_ty = try mod.intFittingRange(min_val, max_val);
2208422618
2208522619 const final_ty = if (is_vector)
22086 try Type.vector(sema.arena, unrefined_ty.vectorLen(), final_elem_ty)
22620 try mod.vectorType(.{
22621 .len = unrefined_ty.vectorLen(mod),
22622 .child = final_elem_ty.toIntern(),
22623 })
2208722624 else
2208822625 final_elem_ty;
2208922626
......@@ -22098,7 +22635,7 @@ fn analyzeMinMax(
2209822635
2209922636fn upgradeToArrayPtr(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, len: u64) !Air.Inst.Ref {
2210022637 const mod = sema.mod;
22101 const info = sema.typeOf(ptr).ptrInfo().data;
22638 const info = sema.typeOf(ptr).ptrInfo(mod);
2210222639 if (info.size == .One) {
2210322640 // Already an array pointer.
2210422641 return ptr;
......@@ -22132,8 +22669,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2213222669 const dest_len = try indexablePtrLenOrNone(sema, block, dest_src, dest_ptr);
2213322670 const src_len = try indexablePtrLenOrNone(sema, block, src_src, src_ptr);
2213422671 const target = sema.mod.getTarget();
22672 const mod = sema.mod;
2213522673
22136 if (dest_ty.isConstPtr()) {
22674 if (dest_ty.isConstPtr(mod)) {
2213722675 return sema.fail(block, dest_src, "cannot memcpy to constant pointer", .{});
2213822676 }
2213922677
......@@ -22194,9 +22732,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2219422732 }
2219522733
2219622734 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
22197 if (!dest_ptr_val.isComptimeMutablePtr()) break :rs dest_src;
22735 if (!dest_ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
2219822736 if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| {
22199 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(target, sema)).?;
22737 const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?;
2220022738 const len = try sema.usizeCast(block, dest_src, len_u64);
2220122739 for (0..len) |i| {
2220222740 const elem_index = try sema.addIntUnsigned(Type.usize, i);
......@@ -22239,12 +22777,12 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2223922777 // lowering. The AIR instruction requires pointers with element types of
2224022778 // equal ABI size.
2224122779
22242 if (dest_ty.zigTypeTag() != .Pointer or src_ty.zigTypeTag() != .Pointer) {
22780 if (dest_ty.zigTypeTag(mod) != .Pointer or src_ty.zigTypeTag(mod) != .Pointer) {
2224322781 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the source or destination iterable is a tuple", .{});
2224422782 }
2224522783
22246 const dest_elem_ty = dest_ty.elemType2();
22247 const src_elem_ty = src_ty.elemType2();
22784 const dest_elem_ty = dest_ty.elemType2(mod);
22785 const src_elem_ty = src_ty.elemType2(mod);
2224822786 if (.ok != try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, true, target, dest_src, src_src)) {
2224922787 return sema.fail(block, src, "TODO: lower @memcpy to a for loop because the element types have different ABI sizes", .{});
2225022788 }
......@@ -22255,7 +22793,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2225522793 var new_dest_ptr = dest_ptr;
2225622794 var new_src_ptr = src_ptr;
2225722795 if (len_val) |val| {
22258 const len = val.toUnsignedInt(target);
22796 const len = val.toUnsignedInt(mod);
2225922797 if (len == 0) {
2226022798 // This AIR instruction guarantees length > 0 if it is comptime-known.
2226122799 return;
......@@ -22268,7 +22806,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2226822806 // Change the src from slice to a many pointer, to avoid multiple ptr
2226922807 // slice extractions in AIR instructions.
2227022808 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
22271 if (new_src_ptr_ty.isSlice()) {
22809 if (new_src_ptr_ty.isSlice(mod)) {
2227222810 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
2227322811 }
2227422812 } else if (dest_len == .none and len_val == null) {
......@@ -22276,7 +22814,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2227622814 const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr);
2227722815 new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false);
2227822816 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
22279 if (new_src_ptr_ty.isSlice()) {
22817 if (new_src_ptr_ty.isSlice(mod)) {
2228022818 new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty);
2228122819 }
2228222820 }
......@@ -22295,14 +22833,30 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2229522833 // Extract raw pointer from dest slice. The AIR instructions could support them, but
2229622834 // it would cause redundant machine code instructions.
2229722835 const new_dest_ptr_ty = sema.typeOf(new_dest_ptr);
22298 const raw_dest_ptr = if (new_dest_ptr_ty.isSlice())
22836 const raw_dest_ptr = if (new_dest_ptr_ty.isSlice(mod))
2229922837 try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty)
22300 else
22301 new_dest_ptr;
22838 else if (new_dest_ptr_ty.ptrSize(mod) == .One) ptr: {
22839 var dest_manyptr_ty_key = mod.intern_pool.indexToKey(new_dest_ptr_ty.toIntern()).ptr_type;
22840 assert(dest_manyptr_ty_key.flags.size == .One);
22841 dest_manyptr_ty_key.child = dest_elem_ty.toIntern();
22842 dest_manyptr_ty_key.flags.size = .Many;
22843 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(dest_manyptr_ty_key), new_dest_ptr, dest_src);
22844 } else new_dest_ptr;
22845
22846 const new_src_ptr_ty = sema.typeOf(new_src_ptr);
22847 const raw_src_ptr = if (new_src_ptr_ty.isSlice(mod))
22848 try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty)
22849 else if (new_src_ptr_ty.ptrSize(mod) == .One) ptr: {
22850 var src_manyptr_ty_key = mod.intern_pool.indexToKey(new_src_ptr_ty.toIntern()).ptr_type;
22851 assert(src_manyptr_ty_key.flags.size == .One);
22852 src_manyptr_ty_key.child = src_elem_ty.toIntern();
22853 src_manyptr_ty_key.flags.size = .Many;
22854 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(src_manyptr_ty_key), new_src_ptr, src_src);
22855 } else new_src_ptr;
2230222856
2230322857 // ok1: dest >= src + len
2230422858 // ok2: src >= dest + len
22305 const src_plus_len = try sema.analyzePtrArithmetic(block, src, new_src_ptr, len, .ptr_add, src_src, src);
22859 const src_plus_len = try sema.analyzePtrArithmetic(block, src, raw_src_ptr, len, .ptr_add, src_src, src);
2230622860 const dest_plus_len = try sema.analyzePtrArithmetic(block, src, raw_dest_ptr, len, .ptr_add, dest_src, src);
2230722861 const ok1 = try block.addBinOp(.cmp_gte, raw_dest_ptr, src_plus_len);
2230822862 const ok2 = try block.addBinOp(.cmp_gte, new_src_ptr, dest_plus_len);
......@@ -22320,6 +22874,9 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2232022874}
2232122875
2232222876fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
22877 const mod = sema.mod;
22878 const gpa = sema.gpa;
22879 const ip = &mod.intern_pool;
2232322880 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2232422881 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
2232522882 const src = inst_data.src();
......@@ -22330,25 +22887,24 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
2233022887 const dest_ptr_ty = sema.typeOf(dest_ptr);
2233122888 try checkMemOperand(sema, block, dest_src, dest_ptr_ty);
2233222889
22333 if (dest_ptr_ty.isConstPtr()) {
22890 if (dest_ptr_ty.isConstPtr(mod)) {
2233422891 return sema.fail(block, dest_src, "cannot memset constant pointer", .{});
2233522892 }
2233622893
22337 const dest_elem_ty = dest_ptr_ty.elemType2();
22338 const target = sema.mod.getTarget();
22894 const dest_elem_ty = dest_ptr_ty.elemType2(mod);
2233922895
2234022896 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: {
22341 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, "len", dest_src);
22897 const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len"), dest_src);
2234222898 const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse
2234322899 break :rs dest_src;
22344 const len_u64 = (try len_val.getUnsignedIntAdvanced(target, sema)).?;
22900 const len_u64 = (try len_val.getUnsignedIntAdvanced(mod, sema)).?;
2234522901 const len = try sema.usizeCast(block, dest_src, len_u64);
2234622902 if (len == 0) {
2234722903 // This AIR instruction guarantees length > 0 if it is comptime-known.
2234822904 return;
2234922905 }
2235022906
22351 if (!ptr_val.isComptimeMutablePtr()) break :rs dest_src;
22907 if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src;
2235222908 if (try sema.resolveMaybeUndefVal(uncoerced_elem)) |_| {
2235322909 for (0..len) |i| {
2235422910 const elem_index = try sema.addIntUnsigned(Type.usize, i);
......@@ -22426,6 +22982,7 @@ fn zirVarExtended(
2242622982 block: *Block,
2242722983 extended: Zir.Inst.Extended.InstData,
2242822984) CompileError!Air.Inst.Ref {
22985 const mod = sema.mod;
2242922986 const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand);
2243022987 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
2243122988 const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
......@@ -22461,47 +23018,33 @@ fn zirVarExtended(
2246123018 else
2246223019 uncasted_init;
2246323020
22464 break :blk (try sema.resolveMaybeUndefVal(init)) orelse
22465 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known");
22466 } else Value.initTag(.unreachable_value);
23021 break :blk ((try sema.resolveMaybeUndefVal(init)) orelse
23022 return sema.failWithNeededComptime(block, init_src, "container level variable initializers must be comptime-known")).toIntern();
23023 } else .none;
2246723024
2246823025 try sema.validateVarType(block, ty_src, var_ty, small.is_extern);
2246923026
22470 const new_var = try sema.gpa.create(Module.Var);
22471 errdefer sema.gpa.destroy(new_var);
22472
22473 log.debug("created variable {*} owner_decl: {*} ({s})", .{
22474 new_var, sema.owner_decl, sema.owner_decl.name,
22475 });
22476
22477 new_var.* = .{
22478 .owner_decl = sema.owner_decl_index,
23027 return sema.addConstant(var_ty, (try mod.intern(.{ .variable = .{
23028 .ty = var_ty.toIntern(),
2247923029 .init = init_val,
23030 .decl = sema.owner_decl_index,
23031 .lib_name = if (lib_name) |lname| (try mod.intern_pool.getOrPutString(
23032 sema.gpa,
23033 try sema.handleExternLibName(block, ty_src, lname),
23034 )).toOptional() else .none,
2248023035 .is_extern = small.is_extern,
22481 .is_mutable = true,
2248223036 .is_threadlocal = small.is_threadlocal,
22483 .is_weak_linkage = false,
22484 .lib_name = null,
22485 };
22486
22487 if (lib_name) |lname| {
22488 new_var.lib_name = try sema.handleExternLibName(block, ty_src, lname);
22489 }
22490
22491 const result = try sema.addConstant(
22492 var_ty,
22493 try Value.Tag.variable.create(sema.arena, new_var),
22494 );
22495 return result;
23037 } })).toValue());
2249623038}
2249723039
2249823040fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
2249923041 const tracy = trace(@src());
2250023042 defer tracy.end();
2250123043
23044 const mod = sema.mod;
2250223045 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
2250323046 const extra = sema.code.extraData(Zir.Inst.FuncFancy, inst_data.payload_index);
22504 const target = sema.mod.getTarget();
23047 const target = mod.getTarget();
2250523048
2250623049 const align_src: LazySrcLoc = .{ .node_offset_fn_type_align = inst_data.src_node };
2250723050 const addrspace_src: LazySrcLoc = .{ .node_offset_fn_type_addrspace = inst_data.src_node };
......@@ -22532,10 +23075,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2253223075 extra_index += body.len;
2253323076
2253423077 const val = try sema.resolveGenericBody(block, align_src, body, inst, Type.u29, "alignment must be comptime-known");
22535 if (val.tag() == .generic_poison) {
23078 if (val.isGenericPoison()) {
2253623079 break :blk null;
2253723080 }
22538 const alignment = @intCast(u32, val.toUnsignedInt(target));
23081 const alignment = @intCast(u32, val.toUnsignedInt(mod));
2253923082 try sema.validateAlign(block, align_src, alignment);
2254023083 if (alignment == target_util.defaultFunctionAlignment(target)) {
2254123084 break :blk 0;
......@@ -22551,7 +23094,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2255123094 },
2255223095 else => |e| return e,
2255323096 };
22554 const alignment = @intCast(u32, align_tv.val.toUnsignedInt(target));
23097 const alignment = @intCast(u32, align_tv.val.toUnsignedInt(mod));
2255523098 try sema.validateAlign(block, align_src, alignment);
2255623099 if (alignment == target_util.defaultFunctionAlignment(target)) {
2255723100 break :blk 0;
......@@ -22568,10 +23111,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2256823111
2256923112 const addrspace_ty = try sema.getBuiltinType("AddressSpace");
2257023113 const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, "addrespace must be comptime-known");
22571 if (val.tag() == .generic_poison) {
23114 if (val.isGenericPoison()) {
2257223115 break :blk null;
2257323116 }
22574 break :blk val.toEnum(std.builtin.AddressSpace);
23117 break :blk mod.toEnum(std.builtin.AddressSpace, val);
2257523118 } else if (extra.data.bits.has_addrspace_ref) blk: {
2257623119 const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2257723120 extra_index += 1;
......@@ -22581,7 +23124,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2258123124 },
2258223125 else => |e| return e,
2258323126 };
22584 break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
23127 break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
2258523128 } else target_util.defaultAddressSpace(target, .function);
2258623129
2258723130 const @"linksection": FuncLinkSection = if (extra.data.bits.has_section_body) blk: {
......@@ -22590,16 +23133,16 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2259023133 const body = sema.code.extra[extra_index..][0..body_len];
2259123134 extra_index += body.len;
2259223135
22593 const ty = Type.initTag(.const_slice_u8);
23136 const ty = Type.slice_const_u8;
2259423137 const val = try sema.resolveGenericBody(block, section_src, body, inst, ty, "linksection must be comptime-known");
22595 if (val.tag() == .generic_poison) {
23138 if (val.isGenericPoison()) {
2259623139 break :blk FuncLinkSection{ .generic = {} };
2259723140 }
22598 break :blk FuncLinkSection{ .explicit = try val.toAllocatedBytes(ty, sema.arena, sema.mod) };
23141 break :blk FuncLinkSection{ .explicit = try val.toIpString(ty, mod) };
2259923142 } else if (extra.data.bits.has_section_ref) blk: {
2260023143 const section_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2260123144 extra_index += 1;
22602 const section_name = sema.resolveConstString(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {
23145 const section_name = sema.resolveConstStringIntern(block, section_src, section_ref, "linksection must be comptime-known") catch |err| switch (err) {
2260323146 error.GenericPoison => {
2260423147 break :blk FuncLinkSection{ .generic = {} };
2260523148 },
......@@ -22616,10 +23159,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2261623159
2261723160 const cc_ty = try sema.getBuiltinType("CallingConvention");
2261823161 const val = try sema.resolveGenericBody(block, cc_src, body, inst, cc_ty, "calling convention must be comptime-known");
22619 if (val.tag() == .generic_poison) {
23162 if (val.isGenericPoison()) {
2262023163 break :blk null;
2262123164 }
22622 break :blk val.toEnum(std.builtin.CallingConvention);
23165 break :blk mod.toEnum(std.builtin.CallingConvention, val);
2262323166 } else if (extra.data.bits.has_cc_ref) blk: {
2262423167 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2262523168 extra_index += 1;
......@@ -22629,7 +23172,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2262923172 },
2263023173 else => |e| return e,
2263123174 };
22632 break :blk cc_tv.val.toEnum(std.builtin.CallingConvention);
23175 break :blk mod.toEnum(std.builtin.CallingConvention, cc_tv.val);
2263323176 } else if (sema.owner_decl.is_exported and has_body)
2263423177 .C
2263523178 else
......@@ -22642,20 +23185,18 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2264223185 extra_index += body.len;
2264323186
2264423187 const val = try sema.resolveGenericBody(block, ret_src, body, inst, Type.type, "return type must be comptime-known");
22645 var buffer: Value.ToTypeBuffer = undefined;
22646 const ty = try val.toType(&buffer).copy(sema.arena);
23188 const ty = val.toType();
2264723189 break :blk ty;
2264823190 } else if (extra.data.bits.has_ret_ty_ref) blk: {
2264923191 const ret_ty_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
2265023192 extra_index += 1;
2265123193 const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref, "return type must be comptime-known") catch |err| switch (err) {
2265223194 error.GenericPoison => {
22653 break :blk Type.initTag(.generic_poison);
23195 break :blk Type.generic_poison;
2265423196 },
2265523197 else => |e| return e,
2265623198 };
22657 var buffer: Value.ToTypeBuffer = undefined;
22658 const ty = try ret_ty_tv.val.toType(&buffer).copy(sema.arena);
23199 const ty = ret_ty_tv.val.toType();
2265923200 break :blk ty;
2266023201 } else Type.void;
2266123202
......@@ -22727,13 +23268,14 @@ fn zirCDefine(
2272723268 block: *Block,
2272823269 extended: Zir.Inst.Extended.InstData,
2272923270) CompileError!Air.Inst.Ref {
23271 const mod = sema.mod;
2273023272 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
2273123273 const name_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
2273223274 const val_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
2273323275
2273423276 const name = try sema.resolveConstString(block, name_src, extra.lhs, "name of macro being undefined must be comptime-known");
2273523277 const rhs = try sema.resolveInst(extra.rhs);
22736 if (sema.typeOf(rhs).zigTypeTag() != .Void) {
23278 if (sema.typeOf(rhs).zigTypeTag(mod) != .Void) {
2273723279 const value = try sema.resolveConstString(block, val_src, extra.rhs, "value of macro being undefined must be comptime-known");
2273823280 try block.c_import_buf.?.writer().print("#define {s} {s}\n", .{ name, value });
2273923281 } else {
......@@ -22799,27 +23341,29 @@ fn resolvePrefetchOptions(
2279923341 src: LazySrcLoc,
2280023342 zir_ref: Zir.Inst.Ref,
2280123343) CompileError!std.builtin.PrefetchOptions {
23344 const mod = sema.mod;
23345 const gpa = sema.gpa;
23346 const ip = &mod.intern_pool;
2280223347 const options_ty = try sema.getBuiltinType("PrefetchOptions");
2280323348 const options = try sema.coerce(block, options_ty, try sema.resolveInst(zir_ref), src);
22804 const target = sema.mod.getTarget();
2280523349
2280623350 const rw_src = sema.maybeOptionsSrc(block, src, "rw");
2280723351 const locality_src = sema.maybeOptionsSrc(block, src, "locality");
2280823352 const cache_src = sema.maybeOptionsSrc(block, src, "cache");
2280923353
22810 const rw = try sema.fieldVal(block, src, options, "rw", rw_src);
23354 const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "rw"), rw_src);
2281123355 const rw_val = try sema.resolveConstValue(block, rw_src, rw, "prefetch read/write must be comptime-known");
2281223356
22813 const locality = try sema.fieldVal(block, src, options, "locality", locality_src);
23357 const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "locality"), locality_src);
2281423358 const locality_val = try sema.resolveConstValue(block, locality_src, locality, "prefetch locality must be comptime-known");
2281523359
22816 const cache = try sema.fieldVal(block, src, options, "cache", cache_src);
23360 const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "cache"), cache_src);
2281723361 const cache_val = try sema.resolveConstValue(block, cache_src, cache, "prefetch cache must be comptime-known");
2281823362
2281923363 return std.builtin.PrefetchOptions{
22820 .rw = rw_val.toEnum(std.builtin.PrefetchOptions.Rw),
22821 .locality = @intCast(u2, locality_val.toUnsignedInt(target)),
22822 .cache = cache_val.toEnum(std.builtin.PrefetchOptions.Cache),
23364 .rw = mod.toEnum(std.builtin.PrefetchOptions.Rw, rw_val),
23365 .locality = @intCast(u2, locality_val.toUnsignedInt(mod)),
23366 .cache = mod.toEnum(std.builtin.PrefetchOptions.Cache, cache_val),
2282323367 };
2282423368}
2282523369
......@@ -22862,34 +23406,40 @@ fn resolveExternOptions(
2286223406 block: *Block,
2286323407 src: LazySrcLoc,
2286423408 zir_ref: Zir.Inst.Ref,
22865) CompileError!std.builtin.ExternOptions {
23409) CompileError!struct {
23410 name: InternPool.NullTerminatedString,
23411 library_name: InternPool.OptionalNullTerminatedString = .none,
23412 linkage: std.builtin.GlobalLinkage = .Strong,
23413 is_thread_local: bool = false,
23414} {
23415 const mod = sema.mod;
23416 const gpa = sema.gpa;
23417 const ip = &mod.intern_pool;
2286623418 const options_inst = try sema.resolveInst(zir_ref);
2286723419 const extern_options_ty = try sema.getBuiltinType("ExternOptions");
2286823420 const options = try sema.coerce(block, extern_options_ty, options_inst, src);
22869 const mod = sema.mod;
2287023421
2287123422 const name_src = sema.maybeOptionsSrc(block, src, "name");
2287223423 const library_src = sema.maybeOptionsSrc(block, src, "library");
2287323424 const linkage_src = sema.maybeOptionsSrc(block, src, "linkage");
2287423425 const thread_local_src = sema.maybeOptionsSrc(block, src, "thread_local");
2287523426
22876 const name_ref = try sema.fieldVal(block, src, options, "name", name_src);
23427 const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name"), name_src);
2287723428 const name_val = try sema.resolveConstValue(block, name_src, name_ref, "name of the extern symbol must be comptime-known");
22878 const name = try name_val.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod);
23429 const name = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
2287923430
22880 const library_name_inst = try sema.fieldVal(block, src, options, "library_name", library_src);
23431 const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name"), library_src);
2288123432 const library_name_val = try sema.resolveConstValue(block, library_src, library_name_inst, "library in which extern symbol is must be comptime-known");
2288223433
22883 const linkage_ref = try sema.fieldVal(block, src, options, "linkage", linkage_src);
23434 const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage"), linkage_src);
2288423435 const linkage_val = try sema.resolveConstValue(block, linkage_src, linkage_ref, "linkage of the extern symbol must be comptime-known");
22885 const linkage = linkage_val.toEnum(std.builtin.GlobalLinkage);
23436 const linkage = mod.toEnum(std.builtin.GlobalLinkage, linkage_val);
2288623437
22887 const is_thread_local = try sema.fieldVal(block, src, options, "is_thread_local", thread_local_src);
23438 const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "is_thread_local"), thread_local_src);
2288823439 const is_thread_local_val = try sema.resolveConstValue(block, thread_local_src, is_thread_local, "threadlocality of the extern symbol must be comptime-known");
2288923440
22890 const library_name = if (!library_name_val.isNull()) blk: {
22891 const payload = library_name_val.castTag(.opt_payload).?.data;
22892 const library_name = try payload.toAllocatedBytes(Type.initTag(.const_slice_u8), sema.arena, mod);
23441 const library_name = if (library_name_val.optionalValue(mod)) |payload| blk: {
23442 const library_name = try payload.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
2289323443 if (library_name.len == 0) {
2289423444 return sema.fail(block, library_src, "library name cannot be empty", .{});
2289523445 }
......@@ -22904,9 +23454,9 @@ fn resolveExternOptions(
2290423454 return sema.fail(block, linkage_src, "extern symbol must use strong or weak linkage", .{});
2290523455 }
2290623456
22907 return std.builtin.ExternOptions{
22908 .name = name,
22909 .library_name = library_name,
23457 return .{
23458 .name = try ip.getOrPutString(gpa, name),
23459 .library_name = try ip.getOrPutStringOpt(gpa, library_name),
2291023460 .linkage = linkage,
2291123461 .is_thread_local = is_thread_local_val.toBool(),
2291223462 };
......@@ -22917,21 +23467,21 @@ fn zirBuiltinExtern(
2291723467 block: *Block,
2291823468 extended: Zir.Inst.Extended.InstData,
2291923469) CompileError!Air.Inst.Ref {
23470 const mod = sema.mod;
2292023471 const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
2292123472 const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
2292223473 const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
2292323474
2292423475 var ty = try sema.resolveType(block, ty_src, extra.lhs);
22925 if (!ty.isPtrAtRuntime()) {
23476 if (!ty.isPtrAtRuntime(mod)) {
2292623477 return sema.fail(block, ty_src, "expected (optional) pointer", .{});
2292723478 }
22928 if (!try sema.validateExternType(ty.childType(), .other)) {
23479 if (!try sema.validateExternType(ty.childType(mod), .other)) {
2292923480 const msg = msg: {
22930 const mod = sema.mod;
2293123481 const msg = try sema.errMsg(block, ty_src, "extern symbol cannot have type '{}'", .{ty.fmt(mod)});
2293223482 errdefer msg.destroy(sema.gpa);
2293323483 const src_decl = sema.mod.declPtr(block.src_decl);
22934 try sema.explainWhyTypeIsNotExtern(msg, ty_src.toSrcLoc(src_decl), ty, .other);
23484 try sema.explainWhyTypeIsNotExtern(msg, ty_src.toSrcLoc(src_decl, mod), ty, .other);
2293523485 break :msg msg;
2293623486 };
2293723487 return sema.failWithOwnedErrorMsg(msg);
......@@ -22945,52 +23495,51 @@ fn zirBuiltinExtern(
2294523495 else => |e| return e,
2294623496 };
2294723497
22948 if (options.linkage == .Weak and !ty.ptrAllowsZero()) {
22949 ty = try Type.optional(sema.arena, ty);
23498 if (options.linkage == .Weak and !ty.ptrAllowsZero(mod)) {
23499 ty = try Type.optional(sema.arena, ty, mod);
2295023500 }
2295123501
2295223502 // TODO check duplicate extern
2295323503
22954 const new_decl_index = try sema.mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, null);
22955 errdefer sema.mod.destroyDecl(new_decl_index);
22956 const new_decl = sema.mod.declPtr(new_decl_index);
22957 new_decl.name = try sema.gpa.dupeZ(u8, options.name);
23504 const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node, null);
23505 errdefer mod.destroyDecl(new_decl_index);
23506 const new_decl = mod.declPtr(new_decl_index);
23507 new_decl.name = options.name;
2295823508
2295923509 {
22960 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
22961 errdefer new_decl_arena.deinit();
22962 const new_decl_arena_allocator = new_decl_arena.allocator();
22963
22964 const new_var = try new_decl_arena_allocator.create(Module.Var);
22965 new_var.* = .{
22966 .owner_decl = sema.owner_decl_index,
22967 .init = Value.initTag(.unreachable_value),
23510 const new_var = try mod.intern(.{ .variable = .{
23511 .ty = ty.toIntern(),
23512 .init = .none,
23513 .decl = sema.owner_decl_index,
2296823514 .is_extern = true,
22969 .is_mutable = false,
23515 .is_const = true,
2297023516 .is_threadlocal = options.is_thread_local,
2297123517 .is_weak_linkage = options.linkage == .Weak,
22972 .lib_name = null,
22973 };
23518 } });
2297423519
2297523520 new_decl.src_line = sema.owner_decl.src_line;
2297623521 // We only access this decl through the decl_ref with the correct type created
2297723522 // below, so this type doesn't matter
22978 new_decl.ty = Type.Tag.init(.anyopaque);
22979 new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);
23523 new_decl.ty = ty;
23524 new_decl.val = new_var.toValue();
2298023525 new_decl.@"align" = 0;
22981 new_decl.@"linksection" = null;
23526 new_decl.@"linksection" = .none;
2298223527 new_decl.has_tv = true;
2298323528 new_decl.analysis = .complete;
22984 new_decl.generation = sema.mod.generation;
22985
22986 try new_decl.finalizeNewArena(&new_decl_arena);
23529 new_decl.generation = mod.generation;
2298723530 }
2298823531
22989 try sema.mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
23532 try mod.declareDeclDependency(sema.owner_decl_index, new_decl_index);
2299023533 try sema.ensureDeclAnalyzed(new_decl_index);
2299123534
22992 const ref = try Value.Tag.decl_ref.create(sema.arena, new_decl_index);
22993 return sema.addConstant(ty, ref);
23535 return sema.addConstant(ty, try mod.getCoerced((try mod.intern(.{ .ptr = .{
23536 .ty = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
23537 .ptr_type => ty.toIntern(),
23538 .opt_type => |child_type| child_type,
23539 else => unreachable,
23540 },
23541 .addr = .{ .decl = new_decl_index },
23542 } })).toValue(), ty));
2299423543}
2299523544
2299623545fn zirWorkItem(
......@@ -23073,7 +23622,7 @@ fn validateVarType(
2307323622 const msg = try sema.errMsg(block, src, "extern variable cannot have type '{}'", .{var_ty.fmt(mod)});
2307423623 errdefer msg.destroy(sema.gpa);
2307523624 const src_decl = mod.declPtr(block.src_decl);
23076 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl), var_ty, .other);
23625 try sema.explainWhyTypeIsNotExtern(msg, src.toSrcLoc(src_decl, mod), var_ty, .other);
2307723626 break :msg msg;
2307823627 };
2307923628 return sema.failWithOwnedErrorMsg(msg);
......@@ -23086,8 +23635,8 @@ fn validateVarType(
2308623635 errdefer msg.destroy(sema.gpa);
2308723636
2308823637 const src_decl = mod.declPtr(block.src_decl);
23089 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl), var_ty);
23090 if (var_ty.zigTypeTag() == .ComptimeInt or var_ty.zigTypeTag() == .ComptimeFloat) {
23638 try sema.explainWhyTypeIsComptime(msg, src.toSrcLoc(src_decl, mod), var_ty);
23639 if (var_ty.zigTypeTag(mod) == .ComptimeInt or var_ty.zigTypeTag(mod) == .ComptimeFloat) {
2309123640 try sema.errNote(block, src, msg, "to modify this variable at runtime, it must be given an explicit fixed-size number type", .{});
2309223641 }
2309323642
......@@ -23101,8 +23650,9 @@ fn validateRunTimeType(
2310123650 var_ty: Type,
2310223651 is_extern: bool,
2310323652) CompileError!bool {
23653 const mod = sema.mod;
2310423654 var ty = var_ty;
23105 while (true) switch (ty.zigTypeTag()) {
23655 while (true) switch (ty.zigTypeTag(mod)) {
2310623656 .Bool,
2310723657 .Int,
2310823658 .Float,
......@@ -23125,23 +23675,22 @@ fn validateRunTimeType(
2312523675 => return false,
2312623676
2312723677 .Pointer => {
23128 const elem_ty = ty.childType();
23129 switch (elem_ty.zigTypeTag()) {
23678 const elem_ty = ty.childType(mod);
23679 switch (elem_ty.zigTypeTag(mod)) {
2313023680 .Opaque => return true,
23131 .Fn => return elem_ty.isFnOrHasRuntimeBits(),
23681 .Fn => return elem_ty.isFnOrHasRuntimeBits(mod),
2313223682 else => ty = elem_ty,
2313323683 }
2313423684 },
2313523685 .Opaque => return is_extern,
2313623686
2313723687 .Optional => {
23138 var buf: Type.Payload.ElemType = undefined;
23139 const child_ty = ty.optionalChild(&buf);
23688 const child_ty = ty.optionalChild(mod);
2314023689 return sema.validateRunTimeType(child_ty, is_extern);
2314123690 },
23142 .Array, .Vector => ty = ty.elemType(),
23691 .Array, .Vector => ty = ty.childType(mod),
2314323692
23144 .ErrorUnion => ty = ty.errorUnionPayload(),
23693 .ErrorUnion => ty = ty.errorUnionPayload(mod),
2314523694
2314623695 .Struct, .Union => {
2314723696 const resolved_ty = try sema.resolveTypeFields(ty);
......@@ -23151,7 +23700,7 @@ fn validateRunTimeType(
2315123700 };
2315223701}
2315323702
23154const TypeSet = std.HashMapUnmanaged(Type, void, Type.HashContext64, std.hash_map.default_max_load_percentage);
23703const TypeSet = std.AutoHashMapUnmanaged(InternPool.Index, void);
2315523704
2315623705fn explainWhyTypeIsComptime(
2315723706 sema: *Sema,
......@@ -23174,7 +23723,7 @@ fn explainWhyTypeIsComptimeInner(
2317423723 type_set: *TypeSet,
2317523724) CompileError!void {
2317623725 const mod = sema.mod;
23177 switch (ty.zigTypeTag()) {
23726 switch (ty.zigTypeTag(mod)) {
2317823727 .Bool,
2317923728 .Int,
2318023729 .Float,
......@@ -23208,12 +23757,12 @@ fn explainWhyTypeIsComptimeInner(
2320823757 },
2320923758
2321023759 .Array, .Vector => {
23211 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.elemType(), type_set);
23760 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(mod), type_set);
2321223761 },
2321323762 .Pointer => {
23214 const elem_ty = ty.elemType2();
23215 if (elem_ty.zigTypeTag() == .Fn) {
23216 const fn_info = elem_ty.fnInfo();
23763 const elem_ty = ty.elemType2(mod);
23764 if (elem_ty.zigTypeTag(mod) == .Fn) {
23765 const fn_info = mod.typeToFunc(elem_ty).?;
2321723766 if (fn_info.is_generic) {
2321823767 try mod.errNoteNonLazy(src_loc, msg, "function is generic", .{});
2321923768 }
......@@ -23221,29 +23770,27 @@ fn explainWhyTypeIsComptimeInner(
2322123770 .Inline => try mod.errNoteNonLazy(src_loc, msg, "function has inline calling convention", .{}),
2322223771 else => {},
2322323772 }
23224 if (fn_info.return_type.comptimeOnly()) {
23773 if (fn_info.return_type.toType().comptimeOnly(mod)) {
2322523774 try mod.errNoteNonLazy(src_loc, msg, "function has a comptime-only return type", .{});
2322623775 }
2322723776 return;
2322823777 }
23229 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.elemType(), type_set);
23778 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.childType(mod), type_set);
2323023779 },
2323123780
2323223781 .Optional => {
23233 var buf: Type.Payload.ElemType = undefined;
23234 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(&buf), type_set);
23782 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.optionalChild(mod), type_set);
2323523783 },
2323623784 .ErrorUnion => {
23237 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(), type_set);
23785 try sema.explainWhyTypeIsComptimeInner(msg, src_loc, ty.errorUnionPayload(mod), type_set);
2323823786 },
2323923787
2324023788 .Struct => {
23241 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
23789 if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return;
2324223790
23243 if (ty.castTag(.@"struct")) |payload| {
23244 const struct_obj = payload.data;
23791 if (mod.typeToStruct(ty)) |struct_obj| {
2324523792 for (struct_obj.fields.values(), 0..) |field, i| {
23246 const field_src_loc = struct_obj.fieldSrcLoc(sema.mod, .{
23793 const field_src_loc = mod.fieldSrcLoc(struct_obj.owner_decl, .{
2324723794 .index = i,
2324823795 .range = .type,
2324923796 });
......@@ -23258,12 +23805,11 @@ fn explainWhyTypeIsComptimeInner(
2325823805 },
2325923806
2326023807 .Union => {
23261 if ((try type_set.getOrPutContext(sema.gpa, ty, .{ .mod = mod })).found_existing) return;
23808 if ((try type_set.getOrPut(sema.gpa, ty.toIntern())).found_existing) return;
2326223809
23263 if (ty.cast(Type.Payload.Union)) |payload| {
23264 const union_obj = payload.data;
23810 if (mod.typeToUnion(ty)) |union_obj| {
2326523811 for (union_obj.fields.values(), 0..) |field, i| {
23266 const field_src_loc = union_obj.fieldSrcLoc(sema.mod, .{
23812 const field_src_loc = mod.fieldSrcLoc(union_obj.owner_decl, .{
2326723813 .index = i,
2326823814 .range = .type,
2326923815 });
......@@ -23295,7 +23841,8 @@ fn validateExternType(
2329523841 ty: Type,
2329623842 position: ExternPosition,
2329723843) !bool {
23298 switch (ty.zigTypeTag()) {
23844 const mod = sema.mod;
23845 switch (ty.zigTypeTag(mod)) {
2329923846 .Type,
2330023847 .ComptimeFloat,
2330123848 .ComptimeInt,
......@@ -23313,8 +23860,8 @@ fn validateExternType(
2331323860 .Float,
2331423861 .AnyFrame,
2331523862 => return true,
23316 .Pointer => return !(ty.isSlice() or try sema.typeRequiresComptime(ty)),
23317 .Int => switch (ty.intInfo(sema.mod.getTarget()).bits) {
23863 .Pointer => return !(ty.isSlice(mod) or try sema.typeRequiresComptime(ty)),
23864 .Int => switch (ty.intInfo(mod).bits) {
2331823865 8, 16, 32, 64, 128 => return true,
2331923866 else => return false,
2332023867 },
......@@ -23323,20 +23870,18 @@ fn validateExternType(
2332323870 const target = sema.mod.getTarget();
2332423871 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
2332523872 // The goal is to experiment with more integrated CPU/GPU code.
23326 if (ty.fnCallingConvention() == .Kernel and (target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64)) {
23873 if (ty.fnCallingConvention(mod) == .Kernel and (target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64)) {
2332723874 return true;
2332823875 }
23329 return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention());
23876 return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(mod));
2333023877 },
2333123878 .Enum => {
23332 var buf: Type.Payload.Bits = undefined;
23333 return sema.validateExternType(ty.intTagType(&buf), position);
23879 return sema.validateExternType(ty.intTagType(mod), position);
2333423880 },
23335 .Struct, .Union => switch (ty.containerLayout()) {
23881 .Struct, .Union => switch (ty.containerLayout(mod)) {
2333623882 .Extern => return true,
2333723883 .Packed => {
23338 const target = sema.mod.getTarget();
23339 const bit_size = try ty.bitSizeAdvanced(target, sema);
23884 const bit_size = try ty.bitSizeAdvanced(mod, sema);
2334023885 switch (bit_size) {
2334123886 8, 16, 32, 64, 128 => return true,
2334223887 else => return false,
......@@ -23346,10 +23891,10 @@ fn validateExternType(
2334623891 },
2334723892 .Array => {
2334823893 if (position == .ret_ty or position == .param_ty) return false;
23349 return sema.validateExternType(ty.elemType2(), .element);
23894 return sema.validateExternType(ty.elemType2(mod), .element);
2335023895 },
23351 .Vector => return sema.validateExternType(ty.elemType2(), .element),
23352 .Optional => return ty.isPtrLikeOptional(),
23896 .Vector => return sema.validateExternType(ty.elemType2(mod), .element),
23897 .Optional => return ty.isPtrLikeOptional(mod),
2335323898 }
2335423899}
2335523900
......@@ -23361,7 +23906,7 @@ fn explainWhyTypeIsNotExtern(
2336123906 position: ExternPosition,
2336223907) CompileError!void {
2336323908 const mod = sema.mod;
23364 switch (ty.zigTypeTag()) {
23909 switch (ty.zigTypeTag(mod)) {
2336523910 .Opaque,
2336623911 .Bool,
2336723912 .Float,
......@@ -23380,17 +23925,17 @@ fn explainWhyTypeIsNotExtern(
2338023925 => return,
2338123926
2338223927 .Pointer => {
23383 if (ty.isSlice()) {
23928 if (ty.isSlice(mod)) {
2338423929 try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{});
2338523930 } else {
23386 const pointee_ty = ty.childType();
23931 const pointee_ty = ty.childType(mod);
2338723932 try mod.errNoteNonLazy(src_loc, msg, "pointer to comptime-only type '{}'", .{pointee_ty.fmt(sema.mod)});
2338823933 try sema.explainWhyTypeIsComptime(msg, src_loc, pointee_ty);
2338923934 }
2339023935 },
2339123936 .Void => try mod.errNoteNonLazy(src_loc, msg, "'void' is a zero bit type; for C 'void' use 'anyopaque'", .{}),
2339223937 .NoReturn => try mod.errNoteNonLazy(src_loc, msg, "'noreturn' is only allowed as a return type", .{}),
23393 .Int => if (!std.math.isPowerOfTwo(ty.intInfo(sema.mod.getTarget()).bits)) {
23938 .Int => if (!std.math.isPowerOfTwo(ty.intInfo(mod).bits)) {
2339423939 try mod.errNoteNonLazy(src_loc, msg, "only integers with power of two bits are extern compatible", .{});
2339523940 } else {
2339623941 try mod.errNoteNonLazy(src_loc, msg, "only integers with 8, 16, 32, 64 and 128 bits are extern compatible", .{});
......@@ -23401,7 +23946,7 @@ fn explainWhyTypeIsNotExtern(
2340123946 try mod.errNoteNonLazy(src_loc, msg, "use '*const ' to make a function pointer type", .{});
2340223947 return;
2340323948 }
23404 switch (ty.fnCallingConvention()) {
23949 switch (ty.fnCallingConvention(mod)) {
2340523950 .Unspecified => try mod.errNoteNonLazy(src_loc, msg, "extern function must specify calling convention", .{}),
2340623951 .Async => try mod.errNoteNonLazy(src_loc, msg, "async function cannot be extern", .{}),
2340723952 .Inline => try mod.errNoteNonLazy(src_loc, msg, "inline function cannot be extern", .{}),
......@@ -23409,8 +23954,7 @@ fn explainWhyTypeIsNotExtern(
2340923954 }
2341023955 },
2341123956 .Enum => {
23412 var buf: Type.Payload.Bits = undefined;
23413 const tag_ty = ty.intTagType(&buf);
23957 const tag_ty = ty.intTagType(mod);
2341423958 try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
2341523959 try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
2341623960 },
......@@ -23422,17 +23966,17 @@ fn explainWhyTypeIsNotExtern(
2342223966 } else if (position == .param_ty) {
2342323967 return mod.errNoteNonLazy(src_loc, msg, "arrays are not allowed as a parameter type", .{});
2342423968 }
23425 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element);
23969 try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element);
2342623970 },
23427 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(), .element),
23971 .Vector => try sema.explainWhyTypeIsNotExtern(msg, src_loc, ty.elemType2(mod), .element),
2342823972 .Optional => try mod.errNoteNonLazy(src_loc, msg, "only pointer like optionals are extern compatible", .{}),
2342923973 }
2343023974}
2343123975
2343223976/// Returns true if `ty` is allowed in packed types.
2343323977/// Does *NOT* require `ty` to be resolved in any way.
23434fn validatePackedType(ty: Type) bool {
23435 switch (ty.zigTypeTag()) {
23978fn validatePackedType(ty: Type, mod: *Module) bool {
23979 switch (ty.zigTypeTag(mod)) {
2343623980 .Type,
2343723981 .ComptimeFloat,
2343823982 .ComptimeInt,
......@@ -23448,7 +23992,7 @@ fn validatePackedType(ty: Type) bool {
2344823992 .Fn,
2344923993 .Array,
2345023994 => return false,
23451 .Optional => return ty.isPtrLikeOptional(),
23995 .Optional => return ty.isPtrLikeOptional(mod),
2345223996 .Void,
2345323997 .Bool,
2345423998 .Float,
......@@ -23456,8 +24000,8 @@ fn validatePackedType(ty: Type) bool {
2345624000 .Vector,
2345724001 .Enum,
2345824002 => return true,
23459 .Pointer => return !ty.isSlice(),
23460 .Struct, .Union => return ty.containerLayout() == .Packed,
24003 .Pointer => return !ty.isSlice(mod),
24004 .Struct, .Union => return ty.containerLayout(mod) == .Packed,
2346124005 }
2346224006}
2346324007
......@@ -23468,7 +24012,7 @@ fn explainWhyTypeIsNotPacked(
2346824012 ty: Type,
2346924013) CompileError!void {
2347024014 const mod = sema.mod;
23471 switch (ty.zigTypeTag()) {
24015 switch (ty.zigTypeTag(mod)) {
2347224016 .Void,
2347324017 .Bool,
2347424018 .Float,
......@@ -23616,7 +24160,6 @@ fn panicWithMsg(
2361624160 msg_inst: Air.Inst.Ref,
2361724161) !void {
2361824162 const mod = sema.mod;
23619 const arena = sema.arena;
2362024163
2362124164 if (!mod.backendSupportsFeature(.panic_fn)) {
2362224165 _ = try block.addNoOp(.trap);
......@@ -23626,16 +24169,24 @@ fn panicWithMsg(
2362624169 const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace");
2362724170 const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty);
2362824171 const target = mod.getTarget();
23629 const ptr_stack_trace_ty = try Type.ptr(arena, mod, .{
23630 .pointee_type = stack_trace_ty,
23631 .@"addrspace" = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
24172 const ptr_stack_trace_ty = try mod.ptrType(.{
24173 .child = stack_trace_ty.toIntern(),
24174 .flags = .{
24175 .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic
24176 },
2363224177 });
23633 const null_stack_trace = try sema.addConstant(
23634 try Type.optional(arena, ptr_stack_trace_ty),
23635 Value.null,
23636 );
23637 const args: [3]Air.Inst.Ref = .{ msg_inst, null_stack_trace, .null_value };
23638 try sema.callBuiltin(block, panic_fn, .auto, &args);
24178 const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern());
24179 const null_stack_trace = try sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{
24180 .ty = opt_ptr_stack_trace_ty.toIntern(),
24181 .val = .none,
24182 } })).toValue());
24183
24184 const opt_usize_ty = try mod.optionalType(.usize_type);
24185 const null_ret_addr = try sema.addConstant(opt_usize_ty, (try mod.intern(.{ .opt = .{
24186 .ty = opt_usize_ty.toIntern(),
24187 .val = .none,
24188 } })).toValue());
24189 try sema.callBuiltin(block, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr });
2363924190}
2364024191
2364124192fn panicUnwrapError(
......@@ -23694,20 +24245,6 @@ fn panicIndexOutOfBounds(
2369424245 try sema.safetyCheckFormatted(parent_block, ok, "panicOutOfBounds", &.{ index, len });
2369524246}
2369624247
23697fn panicStartGreaterThanEnd(
23698 sema: *Sema,
23699 parent_block: *Block,
23700 start: Air.Inst.Ref,
23701 end: Air.Inst.Ref,
23702) !void {
23703 assert(!parent_block.is_comptime);
23704 const ok = try parent_block.addBinOp(.cmp_lte, start, end);
23705 if (!sema.mod.comp.formatted_panics) {
23706 return sema.addSafetyCheck(parent_block, ok, .start_index_greater_than_end);
23707 }
23708 try sema.safetyCheckFormatted(parent_block, ok, "panicStartGreaterThanEnd", &.{ start, end });
23709}
23710
2371124248fn panicInactiveUnionField(
2371224249 sema: *Sema,
2371324250 parent_block: *Block,
......@@ -23731,11 +24268,12 @@ fn panicSentinelMismatch(
2373124268 sentinel_index: Air.Inst.Ref,
2373224269) !void {
2373324270 assert(!parent_block.is_comptime);
24271 const mod = sema.mod;
2373424272 const expected_sentinel_val = maybe_sentinel orelse return;
2373524273 const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val);
2373624274
2373724275 const ptr_ty = sema.typeOf(ptr);
23738 const actual_sentinel = if (ptr_ty.isSlice())
24276 const actual_sentinel = if (ptr_ty.isSlice(mod))
2373924277 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)
2374024278 else blk: {
2374124279 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);
......@@ -23743,7 +24281,7 @@ fn panicSentinelMismatch(
2374324281 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);
2374424282 };
2374524283
23746 const ok = if (sentinel_ty.zigTypeTag() == .Vector) ok: {
24284 const ok = if (sentinel_ty.zigTypeTag(mod) == .Vector) ok: {
2374724285 const eql =
2374824286 try parent_block.addCmpVector(expected_sentinel, actual_sentinel, .eq);
2374924287 break :ok try parent_block.addInst(.{
......@@ -23753,7 +24291,7 @@ fn panicSentinelMismatch(
2375324291 .operation = .And,
2375424292 } },
2375524293 });
23756 } else if (sentinel_ty.isSelfComparable(true))
24294 } else if (sentinel_ty.isSelfComparable(mod, true))
2375724295 try parent_block.addBinOp(.cmp_eq, expected_sentinel, actual_sentinel)
2375824296 else {
2375924297 const panic_fn = try sema.getBuiltin("checkNonScalarSentinel");
......@@ -23805,12 +24343,14 @@ fn safetyPanic(
2380524343 block: *Block,
2380624344 panic_id: PanicId,
2380724345) CompileError!void {
24346 const mod = sema.mod;
24347 const gpa = sema.gpa;
2380824348 const panic_messages_ty = try sema.getBuiltinType("panic_messages");
2380924349 const msg_decl_index = (try sema.namespaceLookup(
2381024350 block,
2381124351 sema.src,
23812 panic_messages_ty.getNamespace().?,
23813 @tagName(panic_id),
24352 panic_messages_ty.getNamespaceIndex(mod).unwrap().?,
24353 try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id)),
2381424354 )).?;
2381524355
2381624356 const msg_inst = try sema.analyzeDeclVal(block, sema.src, msg_decl_index);
......@@ -23842,37 +24382,38 @@ fn fieldVal(
2384224382 block: *Block,
2384324383 src: LazySrcLoc,
2384424384 object: Air.Inst.Ref,
23845 field_name: []const u8,
24385 field_name: InternPool.NullTerminatedString,
2384624386 field_name_src: LazySrcLoc,
2384724387) CompileError!Air.Inst.Ref {
2384824388 // When editing this function, note that there is corresponding logic to be edited
2384924389 // in `fieldPtr`. This function takes a value and returns a value.
2385024390
23851 const arena = sema.arena;
24391 const mod = sema.mod;
24392 const ip = &mod.intern_pool;
2385224393 const object_src = src; // TODO better source location
2385324394 const object_ty = sema.typeOf(object);
2385424395
2385524396 // Zig allows dereferencing a single pointer during field lookup. Note that
2385624397 // we don't actually need to generate the dereference some field lookups, like the
2385724398 // length of arrays and other comptime operations.
23858 const is_pointer_to = object_ty.isSinglePointer();
24399 const is_pointer_to = object_ty.isSinglePointer(mod);
2385924400
2386024401 const inner_ty = if (is_pointer_to)
23861 object_ty.childType()
24402 object_ty.childType(mod)
2386224403 else
2386324404 object_ty;
2386424405
23865 switch (inner_ty.zigTypeTag()) {
24406 switch (inner_ty.zigTypeTag(mod)) {
2386624407 .Array => {
23867 if (mem.eql(u8, field_name, "len")) {
24408 if (ip.stringEqlSlice(field_name, "len")) {
2386824409 return sema.addConstant(
2386924410 Type.usize,
23870 try Value.Tag.int_u64.create(arena, inner_ty.arrayLen()),
24411 try mod.intValue(Type.usize, inner_ty.arrayLen(mod)),
2387124412 );
23872 } else if (mem.eql(u8, field_name, "ptr") and is_pointer_to) {
23873 const ptr_info = object_ty.ptrInfo().data;
23874 const result_ty = try Type.ptr(sema.arena, sema.mod, .{
23875 .pointee_type = ptr_info.pointee_type.childType(),
24413 } else if (ip.stringEqlSlice(field_name, "ptr") and is_pointer_to) {
24414 const ptr_info = object_ty.ptrInfo(mod);
24415 const result_ty = try Type.ptr(sema.arena, mod, .{
24416 .pointee_type = ptr_info.pointee_type.childType(mod),
2387624417 .sentinel = ptr_info.sentinel,
2387724418 .@"align" = ptr_info.@"align",
2387824419 .@"addrspace" = ptr_info.@"addrspace",
......@@ -23889,21 +24430,21 @@ fn fieldVal(
2388924430 return sema.fail(
2389024431 block,
2389124432 field_name_src,
23892 "no member named '{s}' in '{}'",
23893 .{ field_name, object_ty.fmt(sema.mod) },
24433 "no member named '{}' in '{}'",
24434 .{ field_name.fmt(ip), object_ty.fmt(mod) },
2389424435 );
2389524436 }
2389624437 },
2389724438 .Pointer => {
23898 const ptr_info = inner_ty.ptrInfo().data;
24439 const ptr_info = inner_ty.ptrInfo(mod);
2389924440 if (ptr_info.size == .Slice) {
23900 if (mem.eql(u8, field_name, "ptr")) {
24441 if (ip.stringEqlSlice(field_name, "ptr")) {
2390124442 const slice = if (is_pointer_to)
2390224443 try sema.analyzeLoad(block, src, object, object_src)
2390324444 else
2390424445 object;
2390524446 return sema.analyzeSlicePtr(block, object_src, slice, inner_ty);
23906 } else if (mem.eql(u8, field_name, "len")) {
24447 } else if (ip.stringEqlSlice(field_name, "len")) {
2390724448 const slice = if (is_pointer_to)
2390824449 try sema.analyzeLoad(block, src, object, object_src)
2390924450 else
......@@ -23913,8 +24454,8 @@ fn fieldVal(
2391324454 return sema.fail(
2391424455 block,
2391524456 field_name_src,
23916 "no member named '{s}' in '{}'",
23917 .{ field_name, object_ty.fmt(sema.mod) },
24457 "no member named '{}' in '{}'",
24458 .{ field_name.fmt(ip), object_ty.fmt(mod) },
2391824459 );
2391924460 }
2392024461 }
......@@ -23926,66 +24467,74 @@ fn fieldVal(
2392624467 object;
2392724468
2392824469 const val = (try sema.resolveDefinedValue(block, object_src, dereffed_type)).?;
23929 var to_type_buffer: Value.ToTypeBuffer = undefined;
23930 const child_type = val.toType(&to_type_buffer);
24470 const child_type = val.toType();
2393124471
23932 switch (try child_type.zigTypeTagOrPoison()) {
24472 switch (try child_type.zigTypeTagOrPoison(mod)) {
2393324473 .ErrorSet => {
23934 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {
23935 if (payload.data.names.getEntry(field_name)) |entry| {
23936 break :blk entry.key_ptr.*;
23937 }
23938 const msg = msg: {
23939 const msg = try sema.errMsg(block, src, "no error named '{s}' in '{}'", .{
23940 field_name, child_type.fmt(sema.mod),
23941 });
23942 errdefer msg.destroy(sema.gpa);
23943 try sema.addDeclaredHereNote(msg, child_type);
23944 break :msg msg;
23945 };
23946 return sema.failWithOwnedErrorMsg(msg);
23947 } else (try sema.mod.getErrorValue(field_name)).key;
24474 switch (ip.indexToKey(child_type.toIntern())) {
24475 .error_set_type => |error_set_type| blk: {
24476 if (error_set_type.nameIndex(ip, field_name) != null) break :blk;
24477 const msg = msg: {
24478 const msg = try sema.errMsg(block, src, "no error named '{}' in '{}'", .{
24479 field_name.fmt(ip), child_type.fmt(mod),
24480 });
24481 errdefer msg.destroy(sema.gpa);
24482 try sema.addDeclaredHereNote(msg, child_type);
24483 break :msg msg;
24484 };
24485 return sema.failWithOwnedErrorMsg(msg);
24486 },
24487 .inferred_error_set_type => {
24488 return sema.fail(block, src, "TODO handle inferred error sets here", .{});
24489 },
24490 .simple_type => |t| {
24491 assert(t == .anyerror);
24492 _ = try mod.getErrorValue(field_name);
24493 },
24494 else => unreachable,
24495 }
2394824496
23949 return sema.addConstant(
23950 if (!child_type.isAnyError())
23951 try child_type.copy(arena)
23952 else
23953 try Type.Tag.error_set_single.create(arena, name),
23954 try Value.Tag.@"error".create(arena, .{ .name = name }),
23955 );
24497 const error_set_type = if (!child_type.isAnyError(mod))
24498 child_type
24499 else
24500 try mod.singleErrorSetType(field_name);
24501 return sema.addConstant(error_set_type, (try mod.intern(.{ .err = .{
24502 .ty = error_set_type.toIntern(),
24503 .name = field_name,
24504 } })).toValue());
2395624505 },
2395724506 .Union => {
23958 if (child_type.getNamespace()) |namespace| {
24507 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
2395924508 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
2396024509 return inst;
2396124510 }
2396224511 }
2396324512 const union_ty = try sema.resolveTypeFields(child_type);
23964 if (union_ty.unionTagType()) |enum_ty| {
23965 if (enum_ty.enumFieldIndex(field_name)) |field_index_usize| {
24513 if (union_ty.unionTagType(mod)) |enum_ty| {
24514 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index_usize| {
2396624515 const field_index = @intCast(u32, field_index_usize);
2396724516 return sema.addConstant(
2396824517 enum_ty,
23969 try Value.Tag.enum_field_index.create(sema.arena, field_index),
24518 try mod.enumValueFieldIndex(enum_ty, field_index),
2397024519 );
2397124520 }
2397224521 }
2397324522 return sema.failWithBadMemberAccess(block, union_ty, field_name_src, field_name);
2397424523 },
2397524524 .Enum => {
23976 if (child_type.getNamespace()) |namespace| {
24525 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
2397724526 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
2397824527 return inst;
2397924528 }
2398024529 }
23981 const field_index_usize = child_type.enumFieldIndex(field_name) orelse
24530 const field_index_usize = child_type.enumFieldIndex(field_name, mod) orelse
2398224531 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
2398324532 const field_index = @intCast(u32, field_index_usize);
23984 const enum_val = try Value.Tag.enum_field_index.create(arena, field_index);
23985 return sema.addConstant(try child_type.copy(arena), enum_val);
24533 const enum_val = try mod.enumValueFieldIndex(child_type, field_index);
24534 return sema.addConstant(child_type, enum_val);
2398624535 },
2398724536 .Struct, .Opaque => {
23988 if (child_type.getNamespace()) |namespace| {
24537 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
2398924538 if (try sema.namespaceLookupVal(block, src, namespace, field_name)) |inst| {
2399024539 return inst;
2399124540 }
......@@ -23994,10 +24543,10 @@ fn fieldVal(
2399424543 },
2399524544 else => {
2399624545 const msg = msg: {
23997 const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)});
24546 const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(mod)});
2399824547 errdefer msg.destroy(sema.gpa);
23999 if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{});
24000 if (child_type.zigTypeTag() == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{});
24548 if (child_type.isSlice(mod)) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{});
24549 if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{});
2400124550 break :msg msg;
2400224551 };
2400324552 return sema.failWithOwnedErrorMsg(msg);
......@@ -24028,50 +24577,52 @@ fn fieldPtr(
2402824577 block: *Block,
2402924578 src: LazySrcLoc,
2403024579 object_ptr: Air.Inst.Ref,
24031 field_name: []const u8,
24580 field_name: InternPool.NullTerminatedString,
2403224581 field_name_src: LazySrcLoc,
2403324582 initializing: bool,
2403424583) CompileError!Air.Inst.Ref {
2403524584 // When editing this function, note that there is corresponding logic to be edited
2403624585 // in `fieldVal`. This function takes a pointer and returns a pointer.
2403724586
24587 const mod = sema.mod;
24588 const ip = &mod.intern_pool;
2403824589 const object_ptr_src = src; // TODO better source location
2403924590 const object_ptr_ty = sema.typeOf(object_ptr);
24040 const object_ty = switch (object_ptr_ty.zigTypeTag()) {
24041 .Pointer => object_ptr_ty.elemType(),
24042 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(sema.mod)}),
24591 const object_ty = switch (object_ptr_ty.zigTypeTag(mod)) {
24592 .Pointer => object_ptr_ty.childType(mod),
24593 else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty.fmt(mod)}),
2404324594 };
2404424595
2404524596 // Zig allows dereferencing a single pointer during field lookup. Note that
2404624597 // we don't actually need to generate the dereference some field lookups, like the
2404724598 // length of arrays and other comptime operations.
24048 const is_pointer_to = object_ty.isSinglePointer();
24599 const is_pointer_to = object_ty.isSinglePointer(mod);
2404924600
2405024601 const inner_ty = if (is_pointer_to)
24051 object_ty.childType()
24602 object_ty.childType(mod)
2405224603 else
2405324604 object_ty;
2405424605
24055 switch (inner_ty.zigTypeTag()) {
24606 switch (inner_ty.zigTypeTag(mod)) {
2405624607 .Array => {
24057 if (mem.eql(u8, field_name, "len")) {
24608 if (ip.stringEqlSlice(field_name, "len")) {
2405824609 var anon_decl = try block.startAnonDecl();
2405924610 defer anon_decl.deinit();
2406024611 return sema.analyzeDeclRef(try anon_decl.finish(
2406124612 Type.usize,
24062 try Value.Tag.int_u64.create(anon_decl.arena(), inner_ty.arrayLen()),
24613 try mod.intValue(Type.usize, inner_ty.arrayLen(mod)),
2406324614 0, // default alignment
2406424615 ));
2406524616 } else {
2406624617 return sema.fail(
2406724618 block,
2406824619 field_name_src,
24069 "no member named '{s}' in '{}'",
24070 .{ field_name, object_ty.fmt(sema.mod) },
24620 "no member named '{}' in '{}'",
24621 .{ field_name.fmt(ip), object_ty.fmt(mod) },
2407124622 );
2407224623 }
2407324624 },
24074 .Pointer => if (inner_ty.isSlice()) {
24625 .Pointer => if (inner_ty.isSlice(mod)) {
2407524626 const inner_ptr = if (is_pointer_to)
2407624627 try sema.analyzeLoad(block, src, object_ptr, object_ptr_src)
2407724628 else
......@@ -24079,47 +24630,44 @@ fn fieldPtr(
2407924630
2408024631 const attr_ptr_ty = if (is_pointer_to) object_ty else object_ptr_ty;
2408124632
24082 if (mem.eql(u8, field_name, "ptr")) {
24083 const buf = try sema.arena.create(Type.SlicePtrFieldTypeBuffer);
24084 const slice_ptr_ty = inner_ty.slicePtrFieldType(buf);
24633 if (ip.stringEqlSlice(field_name, "ptr")) {
24634 const slice_ptr_ty = inner_ty.slicePtrFieldType(mod);
2408524635
24086 const result_ty = try Type.ptr(sema.arena, sema.mod, .{
24636 const result_ty = try Type.ptr(sema.arena, mod, .{
2408724637 .pointee_type = slice_ptr_ty,
24088 .mutable = attr_ptr_ty.ptrIsMutable(),
24089 .@"volatile" = attr_ptr_ty.isVolatilePtr(),
24090 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(),
24638 .mutable = attr_ptr_ty.ptrIsMutable(mod),
24639 .@"volatile" = attr_ptr_ty.isVolatilePtr(mod),
24640 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(mod),
2409124641 });
2409224642
2409324643 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24094 return sema.addConstant(
24095 result_ty,
24096 try Value.Tag.field_ptr.create(sema.arena, .{
24097 .container_ptr = val,
24098 .container_ty = inner_ty,
24099 .field_index = Value.Payload.Slice.ptr_index,
24100 }),
24101 );
24644 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24645 .ty = result_ty.toIntern(),
24646 .addr = .{ .field = .{
24647 .base = val.toIntern(),
24648 .index = Value.slice_ptr_index,
24649 } },
24650 } })).toValue());
2410224651 }
2410324652 try sema.requireRuntimeBlock(block, src, null);
2410424653
2410524654 return block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr);
24106 } else if (mem.eql(u8, field_name, "len")) {
24107 const result_ty = try Type.ptr(sema.arena, sema.mod, .{
24655 } else if (ip.stringEqlSlice(field_name, "len")) {
24656 const result_ty = try Type.ptr(sema.arena, mod, .{
2410824657 .pointee_type = Type.usize,
24109 .mutable = attr_ptr_ty.ptrIsMutable(),
24110 .@"volatile" = attr_ptr_ty.isVolatilePtr(),
24111 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(),
24658 .mutable = attr_ptr_ty.ptrIsMutable(mod),
24659 .@"volatile" = attr_ptr_ty.isVolatilePtr(mod),
24660 .@"addrspace" = attr_ptr_ty.ptrAddressSpace(mod),
2411224661 });
2411324662
2411424663 if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| {
24115 return sema.addConstant(
24116 result_ty,
24117 try Value.Tag.field_ptr.create(sema.arena, .{
24118 .container_ptr = val,
24119 .container_ty = inner_ty,
24120 .field_index = Value.Payload.Slice.len_index,
24121 }),
24122 );
24664 return sema.addConstant(result_ty, (try mod.intern(.{ .ptr = .{
24665 .ty = result_ty.toIntern(),
24666 .addr = .{ .field = .{
24667 .base = val.toIntern(),
24668 .index = Value.slice_len_index,
24669 } },
24670 } })).toValue());
2412324671 }
2412424672 try sema.requireRuntimeBlock(block, src, null);
2412524673
......@@ -24128,8 +24676,8 @@ fn fieldPtr(
2412824676 return sema.fail(
2412924677 block,
2413024678 field_name_src,
24131 "no member named '{s}' in '{}'",
24132 .{ field_name, object_ty.fmt(sema.mod) },
24679 "no member named '{}' in '{}'",
24680 .{ field_name.fmt(ip), object_ty.fmt(mod) },
2413324681 );
2413424682 }
2413524683 },
......@@ -24142,47 +24690,59 @@ fn fieldPtr(
2414224690 result;
2414324691
2414424692 const val = (sema.resolveDefinedValue(block, src, inner) catch unreachable).?;
24145 var to_type_buffer: Value.ToTypeBuffer = undefined;
24146 const child_type = val.toType(&to_type_buffer);
24693 const child_type = val.toType();
2414724694
24148 switch (child_type.zigTypeTag()) {
24695 switch (child_type.zigTypeTag(mod)) {
2414924696 .ErrorSet => {
24150 // TODO resolve inferred error sets
24151 const name: []const u8 = if (child_type.castTag(.error_set)) |payload| blk: {
24152 if (payload.data.names.getEntry(field_name)) |entry| {
24153 break :blk entry.key_ptr.*;
24154 }
24155 return sema.fail(block, src, "no error named '{s}' in '{}'", .{
24156 field_name, child_type.fmt(sema.mod),
24157 });
24158 } else (try sema.mod.getErrorValue(field_name)).key;
24697 switch (ip.indexToKey(child_type.toIntern())) {
24698 .error_set_type => |error_set_type| blk: {
24699 if (error_set_type.nameIndex(ip, field_name) != null) {
24700 break :blk;
24701 }
24702 return sema.fail(block, src, "no error named '{}' in '{}'", .{
24703 field_name.fmt(ip), child_type.fmt(mod),
24704 });
24705 },
24706 .inferred_error_set_type => {
24707 return sema.fail(block, src, "TODO handle inferred error sets here", .{});
24708 },
24709 .simple_type => |t| {
24710 assert(t == .anyerror);
24711 _ = try mod.getErrorValue(field_name);
24712 },
24713 else => unreachable,
24714 }
2415924715
2416024716 var anon_decl = try block.startAnonDecl();
2416124717 defer anon_decl.deinit();
24718 const error_set_type = if (!child_type.isAnyError(mod))
24719 child_type
24720 else
24721 try mod.singleErrorSetType(field_name);
2416224722 return sema.analyzeDeclRef(try anon_decl.finish(
24163 if (!child_type.isAnyError())
24164 try child_type.copy(anon_decl.arena())
24165 else
24166 try Type.Tag.error_set_single.create(anon_decl.arena(), name),
24167 try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),
24723 error_set_type,
24724 (try mod.intern(.{ .err = .{
24725 .ty = error_set_type.toIntern(),
24726 .name = field_name,
24727 } })).toValue(),
2416824728 0, // default alignment
2416924729 ));
2417024730 },
2417124731 .Union => {
24172 if (child_type.getNamespace()) |namespace| {
24732 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
2417324733 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
2417424734 return inst;
2417524735 }
2417624736 }
2417724737 const union_ty = try sema.resolveTypeFields(child_type);
24178 if (union_ty.unionTagType()) |enum_ty| {
24179 if (enum_ty.enumFieldIndex(field_name)) |field_index| {
24738 if (union_ty.unionTagType(mod)) |enum_ty| {
24739 if (enum_ty.enumFieldIndex(field_name, mod)) |field_index| {
2418024740 const field_index_u32 = @intCast(u32, field_index);
2418124741 var anon_decl = try block.startAnonDecl();
2418224742 defer anon_decl.deinit();
2418324743 return sema.analyzeDeclRef(try anon_decl.finish(
24184 try enum_ty.copy(anon_decl.arena()),
24185 try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
24744 enum_ty,
24745 try mod.enumValueFieldIndex(enum_ty, field_index_u32),
2418624746 0, // default alignment
2418724747 ));
2418824748 }
......@@ -24190,32 +24750,32 @@ fn fieldPtr(
2419024750 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
2419124751 },
2419224752 .Enum => {
24193 if (child_type.getNamespace()) |namespace| {
24753 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
2419424754 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
2419524755 return inst;
2419624756 }
2419724757 }
24198 const field_index = child_type.enumFieldIndex(field_name) orelse {
24758 const field_index = child_type.enumFieldIndex(field_name, mod) orelse {
2419924759 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
2420024760 };
2420124761 const field_index_u32 = @intCast(u32, field_index);
2420224762 var anon_decl = try block.startAnonDecl();
2420324763 defer anon_decl.deinit();
2420424764 return sema.analyzeDeclRef(try anon_decl.finish(
24205 try child_type.copy(anon_decl.arena()),
24206 try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
24765 child_type,
24766 try mod.enumValueFieldIndex(child_type, field_index_u32),
2420724767 0, // default alignment
2420824768 ));
2420924769 },
2421024770 .Struct, .Opaque => {
24211 if (child_type.getNamespace()) |namespace| {
24771 if (child_type.getNamespaceIndex(mod).unwrap()) |namespace| {
2421224772 if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
2421324773 return inst;
2421424774 }
2421524775 }
2421624776 return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
2421724777 },
24218 else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}),
24778 else => return sema.fail(block, src, "type '{}' has no members", .{child_type.fmt(mod)}),
2421924779 }
2422024780 },
2422124781 .Struct => {
......@@ -24252,22 +24812,24 @@ fn fieldCallBind(
2425224812 block: *Block,
2425324813 src: LazySrcLoc,
2425424814 raw_ptr: Air.Inst.Ref,
24255 field_name: []const u8,
24815 field_name: InternPool.NullTerminatedString,
2425624816 field_name_src: LazySrcLoc,
2425724817) CompileError!ResolvedFieldCallee {
2425824818 // When editing this function, note that there is corresponding logic to be edited
2425924819 // in `fieldVal`. This function takes a pointer and returns a pointer.
2426024820
24821 const mod = sema.mod;
24822 const ip = &mod.intern_pool;
2426124823 const raw_ptr_src = src; // TODO better source location
2426224824 const raw_ptr_ty = sema.typeOf(raw_ptr);
24263 const inner_ty = if (raw_ptr_ty.zigTypeTag() == .Pointer and (raw_ptr_ty.ptrSize() == .One or raw_ptr_ty.ptrSize() == .C))
24264 raw_ptr_ty.childType()
24825 const inner_ty = if (raw_ptr_ty.zigTypeTag(mod) == .Pointer and (raw_ptr_ty.ptrSize(mod) == .One or raw_ptr_ty.ptrSize(mod) == .C))
24826 raw_ptr_ty.childType(mod)
2426524827 else
24266 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(sema.mod)});
24828 return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty.fmt(mod)});
2426724829
2426824830 // Optionally dereference a second pointer to get the concrete type.
24269 const is_double_ptr = inner_ty.zigTypeTag() == .Pointer and inner_ty.ptrSize() == .One;
24270 const concrete_ty = if (is_double_ptr) inner_ty.childType() else inner_ty;
24831 const is_double_ptr = inner_ty.zigTypeTag(mod) == .Pointer and inner_ty.ptrSize(mod) == .One;
24832 const concrete_ty = if (is_double_ptr) inner_ty.childType(mod) else inner_ty;
2427124833 const ptr_ty = if (is_double_ptr) inner_ty else raw_ptr_ty;
2427224834 const object_ptr = if (is_double_ptr)
2427324835 try sema.analyzeLoad(block, src, raw_ptr, src)
......@@ -24275,37 +24837,37 @@ fn fieldCallBind(
2427524837 raw_ptr;
2427624838
2427724839 find_field: {
24278 switch (concrete_ty.zigTypeTag()) {
24840 switch (concrete_ty.zigTypeTag(mod)) {
2427924841 .Struct => {
2428024842 const struct_ty = try sema.resolveTypeFields(concrete_ty);
24281 if (struct_ty.castTag(.@"struct")) |struct_obj| {
24282 const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse
24843 if (mod.typeToStruct(struct_ty)) |struct_obj| {
24844 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
2428324845 break :find_field;
2428424846 const field_index = @intCast(u32, field_index_usize);
24285 const field = struct_obj.data.fields.values()[field_index];
24847 const field = struct_obj.fields.values()[field_index];
2428624848
2428724849 return sema.finishFieldCallBind(block, src, ptr_ty, field.ty, field_index, object_ptr);
24288 } else if (struct_ty.isTuple()) {
24289 if (mem.eql(u8, field_name, "len")) {
24290 return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount()) };
24850 } else if (struct_ty.isTuple(mod)) {
24851 if (ip.stringEqlSlice(field_name, "len")) {
24852 return .{ .direct = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod)) };
24853 }
24854 if (field_name.toUnsigned(ip)) |field_index| {
24855 if (field_index >= struct_ty.structFieldCount(mod)) break :find_field;
24856 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index, mod), field_index, object_ptr);
2429124857 }
24292 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
24293 if (field_index >= struct_ty.structFieldCount()) break :find_field;
24294 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr);
24295 } else |_| {}
2429624858 } else {
24297 const max = struct_ty.structFieldCount();
24298 var i: u32 = 0;
24299 while (i < max) : (i += 1) {
24300 if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) {
24301 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr);
24859 const max = struct_ty.structFieldCount(mod);
24860 for (0..max) |i_usize| {
24861 const i = @intCast(u32, i_usize);
24862 if (field_name == struct_ty.structFieldName(i, mod)) {
24863 return sema.finishFieldCallBind(block, src, ptr_ty, struct_ty.structFieldType(i, mod), i, object_ptr);
2430224864 }
2430324865 }
2430424866 }
2430524867 },
2430624868 .Union => {
2430724869 const union_ty = try sema.resolveTypeFields(concrete_ty);
24308 const fields = union_ty.unionFields();
24870 const fields = union_ty.unionFields(mod);
2430924871 const field_index_usize = fields.getIndex(field_name) orelse break :find_field;
2431024872 const field_index = @intCast(u32, field_index_usize);
2431124873 const field = fields.values()[field_index];
......@@ -24321,24 +24883,23 @@ fn fieldCallBind(
2432124883 }
2432224884
2432324885 // If we get here, we need to look for a decl in the struct type instead.
24324 const found_decl = switch (concrete_ty.zigTypeTag()) {
24886 const found_decl = switch (concrete_ty.zigTypeTag(mod)) {
2432524887 .Struct, .Opaque, .Union, .Enum => found_decl: {
24326 if (concrete_ty.getNamespace()) |namespace| {
24888 if (concrete_ty.getNamespaceIndex(mod).unwrap()) |namespace| {
2432724889 if (try sema.namespaceLookup(block, src, namespace, field_name)) |decl_idx| {
2432824890 try sema.addReferencedBy(block, src, decl_idx);
2432924891 const decl_val = try sema.analyzeDeclVal(block, src, decl_idx);
2433024892 const decl_type = sema.typeOf(decl_val);
24331 if (decl_type.zigTypeTag() == .Fn and
24332 decl_type.fnParamLen() >= 1)
24333 {
24334 const first_param_type = decl_type.fnParamType(0);
24335 const first_param_tag = first_param_type.tag();
24893 if (mod.typeToFunc(decl_type)) |func_type| f: {
24894 if (func_type.param_types.len == 0) break :f;
24895
24896 const first_param_type = func_type.param_types[0].toType();
2433624897 // zig fmt: off
24337 if (first_param_tag == .generic_poison or (
24338 first_param_type.zigTypeTag() == .Pointer and
24339 (first_param_type.ptrSize() == .One or
24340 first_param_type.ptrSize() == .C) and
24341 first_param_type.childType().eql(concrete_ty, sema.mod)))
24898 if (first_param_type.isGenericPoison() or (
24899 first_param_type.zigTypeTag(mod) == .Pointer and
24900 (first_param_type.ptrSize(mod) == .One or
24901 first_param_type.ptrSize(mod) == .C) and
24902 first_param_type.childType(mod).eql(concrete_ty, mod)))
2434224903 {
2434324904 // zig fmt: on
2434424905 // Note that if the param type is generic poison, we know that it must
......@@ -24350,32 +24911,31 @@ fn fieldCallBind(
2435024911 .func_inst = decl_val,
2435124912 .arg0_inst = object_ptr,
2435224913 } };
24353 } else if (first_param_type.eql(concrete_ty, sema.mod)) {
24914 } else if (first_param_type.eql(concrete_ty, mod)) {
2435424915 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
2435524916 return .{ .method = .{
2435624917 .func_inst = decl_val,
2435724918 .arg0_inst = deref,
2435824919 } };
24359 } else if (first_param_type.zigTypeTag() == .Optional) {
24360 var opt_buf: Type.Payload.ElemType = undefined;
24361 const child = first_param_type.optionalChild(&opt_buf);
24362 if (child.eql(concrete_ty, sema.mod)) {
24920 } else if (first_param_type.zigTypeTag(mod) == .Optional) {
24921 const child = first_param_type.optionalChild(mod);
24922 if (child.eql(concrete_ty, mod)) {
2436324923 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
2436424924 return .{ .method = .{
2436524925 .func_inst = decl_val,
2436624926 .arg0_inst = deref,
2436724927 } };
24368 } else if (child.zigTypeTag() == .Pointer and
24369 child.ptrSize() == .One and
24370 child.childType().eql(concrete_ty, sema.mod))
24928 } else if (child.zigTypeTag(mod) == .Pointer and
24929 child.ptrSize(mod) == .One and
24930 child.childType(mod).eql(concrete_ty, mod))
2437124931 {
2437224932 return .{ .method = .{
2437324933 .func_inst = decl_val,
2437424934 .arg0_inst = object_ptr,
2437524935 } };
2437624936 }
24377 } else if (first_param_type.zigTypeTag() == .ErrorUnion and
24378 first_param_type.errorUnionPayload().eql(concrete_ty, sema.mod))
24937 } else if (first_param_type.zigTypeTag(mod) == .ErrorUnion and
24938 first_param_type.errorUnionPayload(mod).eql(concrete_ty, mod))
2437924939 {
2438024940 const deref = try sema.analyzeLoad(block, src, object_ptr, src);
2438124941 return .{ .method = .{
......@@ -24393,12 +24953,15 @@ fn fieldCallBind(
2439324953 };
2439424954
2439524955 const msg = msg: {
24396 const msg = try sema.errMsg(block, src, "no field or member function named '{s}' in '{}'", .{ field_name, concrete_ty.fmt(sema.mod) });
24956 const msg = try sema.errMsg(block, src, "no field or member function named '{}' in '{}'", .{
24957 field_name.fmt(ip),
24958 concrete_ty.fmt(mod),
24959 });
2439724960 errdefer msg.destroy(sema.gpa);
2439824961 try sema.addDeclaredHereNote(msg, concrete_ty);
2439924962 if (found_decl) |decl_idx| {
24400 const decl = sema.mod.declPtr(decl_idx);
24401 try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "'{s}' is not a member function", .{field_name});
24963 const decl = mod.declPtr(decl_idx);
24964 try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "'{}' is not a member function", .{field_name.fmt(ip)});
2440224965 }
2440324966 break :msg msg;
2440424967 };
......@@ -24414,29 +24977,29 @@ fn finishFieldCallBind(
2441424977 field_index: u32,
2441524978 object_ptr: Air.Inst.Ref,
2441624979) CompileError!ResolvedFieldCallee {
24980 const mod = sema.mod;
2441724981 const arena = sema.arena;
24418 const ptr_field_ty = try Type.ptr(arena, sema.mod, .{
24982 const ptr_field_ty = try Type.ptr(arena, mod, .{
2441924983 .pointee_type = field_ty,
24420 .mutable = ptr_ty.ptrIsMutable(),
24421 .@"addrspace" = ptr_ty.ptrAddressSpace(),
24984 .mutable = ptr_ty.ptrIsMutable(mod),
24985 .@"addrspace" = ptr_ty.ptrAddressSpace(mod),
2442224986 });
2442324987
24424 const container_ty = ptr_ty.childType();
24425 if (container_ty.zigTypeTag() == .Struct) {
24426 if (container_ty.structFieldValueComptime(field_index)) |default_val| {
24988 const container_ty = ptr_ty.childType(mod);
24989 if (container_ty.zigTypeTag(mod) == .Struct) {
24990 if (try container_ty.structFieldValueComptime(mod, field_index)) |default_val| {
2442724991 return .{ .direct = try sema.addConstant(field_ty, default_val) };
2442824992 }
2442924993 }
2443024994
2443124995 if (try sema.resolveDefinedValue(block, src, object_ptr)) |struct_ptr_val| {
24432 const pointer = try sema.addConstant(
24433 ptr_field_ty,
24434 try Value.Tag.field_ptr.create(arena, .{
24435 .container_ptr = struct_ptr_val,
24436 .container_ty = container_ty,
24437 .field_index = field_index,
24438 }),
24439 );
24996 const pointer = try sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
24997 .ty = ptr_field_ty.toIntern(),
24998 .addr = .{ .field = .{
24999 .base = struct_ptr_val.toIntern(),
25000 .index = field_index,
25001 } },
25002 } })).toValue());
2444025003 return .{ .direct = try sema.analyzeLoad(block, src, pointer, src) };
2444125004 }
2444225005
......@@ -24449,19 +25012,20 @@ fn namespaceLookup(
2444925012 sema: *Sema,
2445025013 block: *Block,
2445125014 src: LazySrcLoc,
24452 namespace: *Namespace,
24453 decl_name: []const u8,
25015 namespace: Namespace.Index,
25016 decl_name: InternPool.NullTerminatedString,
2445425017) CompileError!?Decl.Index {
25018 const mod = sema.mod;
2445525019 const gpa = sema.gpa;
2445625020 if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl_index| {
24457 const decl = sema.mod.declPtr(decl_index);
24458 if (!decl.is_pub and decl.getFileScope() != block.getFileScope()) {
25021 const decl = mod.declPtr(decl_index);
25022 if (!decl.is_pub and decl.getFileScope(mod) != block.getFileScope(mod)) {
2445925023 const msg = msg: {
24460 const msg = try sema.errMsg(block, src, "'{s}' is not marked 'pub'", .{
24461 decl_name,
25024 const msg = try sema.errMsg(block, src, "'{}' is not marked 'pub'", .{
25025 decl_name.fmt(&mod.intern_pool),
2446225026 });
2446325027 errdefer msg.destroy(gpa);
24464 try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{});
25028 try mod.errNoteNonLazy(decl.srcLoc(mod), msg, "declared here", .{});
2446525029 break :msg msg;
2446625030 };
2446725031 return sema.failWithOwnedErrorMsg(msg);
......@@ -24475,8 +25039,8 @@ fn namespaceLookupRef(
2447525039 sema: *Sema,
2447625040 block: *Block,
2447725041 src: LazySrcLoc,
24478 namespace: *Namespace,
24479 decl_name: []const u8,
25042 namespace: Namespace.Index,
25043 decl_name: InternPool.NullTerminatedString,
2448025044) CompileError!?Air.Inst.Ref {
2448125045 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
2448225046 try sema.addReferencedBy(block, src, decl);
......@@ -24487,8 +25051,8 @@ fn namespaceLookupVal(
2448725051 sema: *Sema,
2448825052 block: *Block,
2448925053 src: LazySrcLoc,
24490 namespace: *Namespace,
24491 decl_name: []const u8,
25054 namespace: Namespace.Index,
25055 decl_name: InternPool.NullTerminatedString,
2449225056) CompileError!?Air.Inst.Ref {
2449325057 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
2449425058 return try sema.analyzeDeclVal(block, src, decl);
......@@ -24499,29 +25063,30 @@ fn structFieldPtr(
2449925063 block: *Block,
2450025064 src: LazySrcLoc,
2450125065 struct_ptr: Air.Inst.Ref,
24502 field_name: []const u8,
25066 field_name: InternPool.NullTerminatedString,
2450325067 field_name_src: LazySrcLoc,
2450425068 unresolved_struct_ty: Type,
2450525069 initializing: bool,
2450625070) CompileError!Air.Inst.Ref {
24507 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
25071 const mod = sema.mod;
25072 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
2450825073
2450925074 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
2451025075 try sema.resolveStructLayout(struct_ty);
2451125076
24512 if (struct_ty.isTuple()) {
24513 if (mem.eql(u8, field_name, "len")) {
24514 const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount());
25077 if (struct_ty.isTuple(mod)) {
25078 if (mod.intern_pool.stringEqlSlice(field_name, "len")) {
25079 const len_inst = try sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount(mod));
2451525080 return sema.analyzeRef(block, src, len_inst);
2451625081 }
2451725082 const field_index = try sema.tupleFieldIndex(block, struct_ty, field_name, field_name_src);
2451825083 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
24519 } else if (struct_ty.isAnonStruct()) {
25084 } else if (struct_ty.isAnonStruct(mod)) {
2452025085 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
2452125086 return sema.tupleFieldPtr(block, src, struct_ptr, field_name_src, field_index, initializing);
2452225087 }
2452325088
24524 const struct_obj = struct_ty.castTag(.@"struct").?.data;
25089 const struct_obj = mod.typeToStruct(struct_ty).?;
2452525090
2452625091 const field_index_big = struct_obj.fields.getIndex(field_name) orelse
2452725092 return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
......@@ -24540,14 +25105,15 @@ fn structFieldPtrByIndex(
2454025105 struct_ty: Type,
2454125106 initializing: bool,
2454225107) CompileError!Air.Inst.Ref {
24543 if (struct_ty.isAnonStruct()) {
25108 const mod = sema.mod;
25109 if (struct_ty.isAnonStruct(mod)) {
2454425110 return sema.tupleFieldPtr(block, src, struct_ptr, field_src, field_index, initializing);
2454525111 }
2454625112
24547 const struct_obj = struct_ty.castTag(.@"struct").?.data;
25113 const struct_obj = mod.typeToStruct(struct_ty).?;
2454825114 const field = struct_obj.fields.values()[field_index];
2454925115 const struct_ptr_ty = sema.typeOf(struct_ptr);
24550 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo().data;
25116 const struct_ptr_ty_info = struct_ptr_ty.ptrInfo(mod);
2455125117
2455225118 var ptr_ty_data: Type.Payload.Pointer.Data = .{
2455325119 .pointee_type = field.ty,
......@@ -24556,7 +25122,7 @@ fn structFieldPtrByIndex(
2455625122 .@"addrspace" = struct_ptr_ty_info.@"addrspace",
2455725123 };
2455825124
24559 const target = sema.mod.getTarget();
25125 const target = mod.getTarget();
2456025126
2456125127 if (struct_obj.layout == .Packed) {
2456225128 comptime assert(Type.packed_struct_layout_version == 2);
......@@ -24568,7 +25134,7 @@ fn structFieldPtrByIndex(
2456825134 if (i == field_index) {
2456925135 ptr_ty_data.bit_offset = running_bits;
2457025136 }
24571 running_bits += @intCast(u16, f.ty.bitSize(target));
25137 running_bits += @intCast(u16, f.ty.bitSize(mod));
2457225138 }
2457325139 ptr_ty_data.host_size = (running_bits + 7) / 8;
2457425140
......@@ -24582,7 +25148,7 @@ fn structFieldPtrByIndex(
2458225148 const parent_align = if (struct_ptr_ty_info.@"align" != 0)
2458325149 struct_ptr_ty_info.@"align"
2458425150 else
24585 struct_ptr_ty_info.pointee_type.abiAlignment(target);
25151 struct_ptr_ty_info.pointee_type.abiAlignment(mod);
2458625152 ptr_ty_data.@"align" = parent_align;
2458725153
2458825154 // If the field happens to be byte-aligned, simplify the pointer type.
......@@ -24596,8 +25162,8 @@ fn structFieldPtrByIndex(
2459625162 if (parent_align != 0 and ptr_ty_data.bit_offset % 8 == 0 and
2459725163 target.cpu.arch.endian() == .Little)
2459825164 {
24599 const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(target);
24600 const elem_size_bits = ptr_ty_data.pointee_type.bitSize(target);
25165 const elem_size_bytes = ptr_ty_data.pointee_type.abiSize(mod);
25166 const elem_size_bits = ptr_ty_data.pointee_type.bitSize(mod);
2460125167 if (elem_size_bytes * 8 == elem_size_bits) {
2460225168 const byte_offset = ptr_ty_data.bit_offset / 8;
2460325169 const new_align = @as(u32, 1) << @intCast(u5, @ctz(byte_offset | parent_align));
......@@ -24610,25 +25176,25 @@ fn structFieldPtrByIndex(
2461025176 ptr_ty_data.@"align" = field.abi_align;
2461125177 }
2461225178
24613 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, ptr_ty_data);
25179 const ptr_field_ty = try Type.ptr(sema.arena, mod, ptr_ty_data);
2461425180
2461525181 if (field.is_comptime) {
24616 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
24617 .field_ty = try field.ty.copy(sema.arena),
24618 .field_val = try field.default_val.copy(sema.arena),
24619 });
24620 return sema.addConstant(ptr_field_ty, val);
25182 const val = try mod.intern(.{ .ptr = .{
25183 .ty = ptr_field_ty.toIntern(),
25184 .addr = .{ .comptime_field = field.default_val },
25185 } });
25186 return sema.addConstant(ptr_field_ty, val.toValue());
2462125187 }
2462225188
2462325189 if (try sema.resolveDefinedValue(block, src, struct_ptr)) |struct_ptr_val| {
24624 return sema.addConstant(
24625 ptr_field_ty,
24626 try Value.Tag.field_ptr.create(sema.arena, .{
24627 .container_ptr = struct_ptr_val,
24628 .container_ty = struct_ptr_ty.childType(),
24629 .field_index = field_index,
24630 }),
24631 );
25190 const val = try mod.intern(.{ .ptr = .{
25191 .ty = ptr_field_ty.toIntern(),
25192 .addr = .{ .field = .{
25193 .base = try struct_ptr_val.intern(struct_ptr_ty, mod),
25194 .index = field_index,
25195 } },
25196 } });
25197 return sema.addConstant(ptr_field_ty, val.toValue());
2463225198 }
2463325199
2463425200 try sema.requireRuntimeBlock(block, src, null);
......@@ -24640,21 +25206,17 @@ fn structFieldVal(
2464025206 block: *Block,
2464125207 src: LazySrcLoc,
2464225208 struct_byval: Air.Inst.Ref,
24643 field_name: []const u8,
25209 field_name: InternPool.NullTerminatedString,
2464425210 field_name_src: LazySrcLoc,
2464525211 unresolved_struct_ty: Type,
2464625212) CompileError!Air.Inst.Ref {
24647 assert(unresolved_struct_ty.zigTypeTag() == .Struct);
25213 const mod = sema.mod;
25214 assert(unresolved_struct_ty.zigTypeTag(mod) == .Struct);
2464825215
2464925216 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
24650 switch (struct_ty.tag()) {
24651 .tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
24652 .anon_struct => {
24653 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
24654 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
24655 },
24656 .@"struct" => {
24657 const struct_obj = struct_ty.castTag(.@"struct").?.data;
25217 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
25218 .struct_type => |struct_type| {
25219 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
2465825220 if (struct_obj.is_tuple) return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
2465925221
2466025222 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
......@@ -24663,22 +25225,28 @@ fn structFieldVal(
2466325225 const field = struct_obj.fields.values()[field_index];
2466425226
2466525227 if (field.is_comptime) {
24666 return sema.addConstant(field.ty, field.default_val);
25228 return sema.addConstant(field.ty, field.default_val.toValue());
2466725229 }
2466825230
2466925231 if (try sema.resolveMaybeUndefVal(struct_byval)) |struct_val| {
24670 if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
25232 if (struct_val.isUndef(mod)) return sema.addConstUndef(field.ty);
2467125233 if ((try sema.typeHasOnePossibleValue(field.ty))) |opv| {
2467225234 return sema.addConstant(field.ty, opv);
2467325235 }
24674
24675 const field_values = struct_val.castTag(.aggregate).?.data;
24676 return sema.addConstant(field.ty, field_values[field_index]);
25236 return sema.addConstant(field.ty, try struct_val.fieldValue(mod, field_index));
2467725237 }
2467825238
2467925239 try sema.requireRuntimeBlock(block, src, null);
2468025240 return block.addStructFieldVal(struct_byval, field_index, field.ty);
2468125241 },
25242 .anon_struct_type => |anon_struct| {
25243 if (anon_struct.names.len == 0) {
25244 return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
25245 } else {
25246 const field_index = try sema.anonStructFieldIndex(block, struct_ty, field_name, field_name_src);
25247 return sema.tupleFieldValByIndex(block, src, struct_byval, field_index, struct_ty);
25248 }
25249 },
2468225250 else => unreachable,
2468325251 }
2468425252}
......@@ -24688,12 +25256,13 @@ fn tupleFieldVal(
2468825256 block: *Block,
2468925257 src: LazySrcLoc,
2469025258 tuple_byval: Air.Inst.Ref,
24691 field_name: []const u8,
25259 field_name: InternPool.NullTerminatedString,
2469225260 field_name_src: LazySrcLoc,
2469325261 tuple_ty: Type,
2469425262) CompileError!Air.Inst.Ref {
24695 if (mem.eql(u8, field_name, "len")) {
24696 return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount());
25263 const mod = sema.mod;
25264 if (mod.intern_pool.stringEqlSlice(field_name, "len")) {
25265 return sema.addIntUnsigned(Type.usize, tuple_ty.structFieldCount(mod));
2469725266 }
2469825267 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_name_src);
2469925268 return sema.tupleFieldValByIndex(block, src, tuple_byval, field_index, tuple_ty);
......@@ -24704,19 +25273,20 @@ fn tupleFieldIndex(
2470425273 sema: *Sema,
2470525274 block: *Block,
2470625275 tuple_ty: Type,
24707 field_name: []const u8,
25276 field_name: InternPool.NullTerminatedString,
2470825277 field_name_src: LazySrcLoc,
2470925278) CompileError!u32 {
24710 assert(!std.mem.eql(u8, field_name, "len"));
24711 if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
24712 if (field_index < tuple_ty.structFieldCount()) return field_index;
24713 return sema.fail(block, field_name_src, "index '{s}' out of bounds of tuple '{}'", .{
24714 field_name, tuple_ty.fmt(sema.mod),
25279 const mod = sema.mod;
25280 assert(!mod.intern_pool.stringEqlSlice(field_name, "len"));
25281 if (field_name.toUnsigned(&mod.intern_pool)) |field_index| {
25282 if (field_index < tuple_ty.structFieldCount(mod)) return field_index;
25283 return sema.fail(block, field_name_src, "index '{}' out of bounds of tuple '{}'", .{
25284 field_name.fmt(&mod.intern_pool), tuple_ty.fmt(mod),
2471525285 });
24716 } else |_| {}
25286 }
2471725287
24718 return sema.fail(block, field_name_src, "no field named '{s}' in tuple '{}'", .{
24719 field_name, tuple_ty.fmt(sema.mod),
25288 return sema.fail(block, field_name_src, "no field named '{}' in tuple '{}'", .{
25289 field_name.fmt(&mod.intern_pool), tuple_ty.fmt(mod),
2472025290 });
2472125291}
2472225292
......@@ -24728,22 +25298,29 @@ fn tupleFieldValByIndex(
2472825298 field_index: u32,
2472925299 tuple_ty: Type,
2473025300) CompileError!Air.Inst.Ref {
24731 const field_ty = tuple_ty.structFieldType(field_index);
25301 const mod = sema.mod;
25302 const field_ty = tuple_ty.structFieldType(field_index, mod);
2473225303
24733 if (tuple_ty.structFieldValueComptime(field_index)) |default_value| {
25304 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
2473425305 return sema.addConstant(field_ty, default_value);
2473525306 }
2473625307
2473725308 if (try sema.resolveMaybeUndefVal(tuple_byval)) |tuple_val| {
24738 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
2473925309 if ((try sema.typeHasOnePossibleValue(field_ty))) |opv| {
2474025310 return sema.addConstant(field_ty, opv);
2474125311 }
24742 const field_values = tuple_val.castTag(.aggregate).?.data;
24743 return sema.addConstant(field_ty, field_values[field_index]);
25312 return switch (mod.intern_pool.indexToKey(tuple_val.toIntern())) {
25313 .undef => sema.addConstUndef(field_ty),
25314 .aggregate => |aggregate| sema.addConstant(field_ty, switch (aggregate.storage) {
25315 .bytes => |bytes| try mod.intValue(Type.u8, bytes[0]),
25316 .elems => |elems| elems[field_index].toValue(),
25317 .repeated_elem => |elem| elem.toValue(),
25318 }),
25319 else => unreachable,
25320 };
2474425321 }
2474525322
24746 if (tuple_ty.structFieldValueComptime(field_index)) |default_val| {
25323 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
2474725324 return sema.addConstant(field_ty, default_val);
2474825325 }
2474925326
......@@ -24756,33 +25333,38 @@ fn unionFieldPtr(
2475625333 block: *Block,
2475725334 src: LazySrcLoc,
2475825335 union_ptr: Air.Inst.Ref,
24759 field_name: []const u8,
25336 field_name: InternPool.NullTerminatedString,
2476025337 field_name_src: LazySrcLoc,
2476125338 unresolved_union_ty: Type,
2476225339 initializing: bool,
2476325340) CompileError!Air.Inst.Ref {
2476425341 const arena = sema.arena;
24765 assert(unresolved_union_ty.zigTypeTag() == .Union);
25342 const mod = sema.mod;
25343 const ip = &mod.intern_pool;
25344
25345 assert(unresolved_union_ty.zigTypeTag(mod) == .Union);
2476625346
2476725347 const union_ptr_ty = sema.typeOf(union_ptr);
2476825348 const union_ty = try sema.resolveTypeFields(unresolved_union_ty);
24769 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
25349 const union_obj = mod.typeToUnion(union_ty).?;
2477025350 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
2477125351 const field = union_obj.fields.values()[field_index];
24772 const ptr_field_ty = try Type.ptr(arena, sema.mod, .{
25352 const ptr_field_ty = try Type.ptr(arena, mod, .{
2477325353 .pointee_type = field.ty,
24774 .mutable = union_ptr_ty.ptrIsMutable(),
24775 .@"volatile" = union_ptr_ty.isVolatilePtr(),
24776 .@"addrspace" = union_ptr_ty.ptrAddressSpace(),
25354 .mutable = union_ptr_ty.ptrIsMutable(mod),
25355 .@"volatile" = union_ptr_ty.isVolatilePtr(mod),
25356 .@"addrspace" = union_ptr_ty.ptrAddressSpace(mod),
2477725357 });
24778 const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?);
25358 const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name, mod).?);
2477925359
24780 if (initializing and field.ty.zigTypeTag() == .NoReturn) {
25360 if (initializing and field.ty.zigTypeTag(mod) == .NoReturn) {
2478125361 const msg = msg: {
2478225362 const msg = try sema.errMsg(block, src, "cannot initialize 'noreturn' field of union", .{});
2478325363 errdefer msg.destroy(sema.gpa);
2478425364
24785 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
25365 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
25366 field_name.fmt(ip),
25367 });
2478625368 try sema.addDeclaredHereNote(msg, union_ty);
2478725369 break :msg msg;
2478825370 };
......@@ -24794,21 +25376,20 @@ fn unionFieldPtr(
2479425376 .Auto => if (!initializing) {
2479525377 const union_val = (try sema.pointerDeref(block, src, union_ptr_val, union_ptr_ty)) orelse
2479625378 break :ct;
24797 if (union_val.isUndef()) {
25379 if (union_val.isUndef(mod)) {
2479825380 return sema.failWithUseOfUndef(block, src);
2479925381 }
24800 const tag_and_val = union_val.castTag(.@"union").?.data;
24801 var field_tag_buf: Value.Payload.U32 = .{
24802 .base = .{ .tag = .enum_field_index },
24803 .data = enum_field_index,
24804 };
24805 const field_tag = Value.initPayload(&field_tag_buf.base);
24806 const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod);
25382 const un = ip.indexToKey(union_val.toIntern()).un;
25383 const field_tag = try mod.enumValueFieldIndex(union_obj.tag_ty, enum_field_index);
25384 const tag_matches = un.tag == field_tag.toIntern();
2480725385 if (!tag_matches) {
2480825386 const msg = msg: {
24809 const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data;
24810 const active_field_name = union_obj.tag_ty.enumFieldName(active_index);
24811 const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name });
25387 const active_index = union_obj.tag_ty.enumTagFieldIndex(un.tag.toValue(), mod).?;
25388 const active_field_name = union_obj.tag_ty.enumFieldName(active_index, mod);
25389 const msg = try sema.errMsg(block, src, "access of union field '{}' while field '{}' is active", .{
25390 field_name.fmt(ip),
25391 active_field_name.fmt(ip),
25392 });
2481225393 errdefer msg.destroy(sema.gpa);
2481325394 try sema.addDeclaredHereNote(msg, union_ty);
2481425395 break :msg msg;
......@@ -24818,28 +25399,27 @@ fn unionFieldPtr(
2481825399 },
2481925400 .Packed, .Extern => {},
2482025401 }
24821 return sema.addConstant(
24822 ptr_field_ty,
24823 try Value.Tag.field_ptr.create(arena, .{
24824 .container_ptr = union_ptr_val,
24825 .container_ty = union_ty,
24826 .field_index = field_index,
24827 }),
24828 );
25402 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25403 .ty = ptr_field_ty.toIntern(),
25404 .addr = .{ .field = .{
25405 .base = union_ptr_val.toIntern(),
25406 .index = field_index,
25407 } },
25408 } })).toValue());
2482925409 }
2483025410
2483125411 try sema.requireRuntimeBlock(block, src, null);
2483225412 if (!initializing and union_obj.layout == .Auto and block.wantSafety() and
24833 union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1)
25413 union_ty.unionTagTypeSafety(mod) != null and union_obj.fields.count() > 1)
2483425414 {
24835 const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);
25415 const wanted_tag_val = try mod.enumValueFieldIndex(union_obj.tag_ty, enum_field_index);
2483625416 const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);
2483725417 // TODO would it be better if get_union_tag supported pointers to unions?
2483825418 const union_val = try block.addTyOp(.load, union_ty, union_ptr);
2483925419 const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_val);
2484025420 try sema.panicInactiveUnionField(block, active_tag, wanted_tag);
2484125421 }
24842 if (field.ty.zigTypeTag() == .NoReturn) {
25422 if (field.ty.zigTypeTag(mod) == .NoReturn) {
2484325423 _ = try block.addNoOp(.unreach);
2484425424 return Air.Inst.Ref.unreachable_value;
2484525425 }
......@@ -24851,37 +25431,37 @@ fn unionFieldVal(
2485125431 block: *Block,
2485225432 src: LazySrcLoc,
2485325433 union_byval: Air.Inst.Ref,
24854 field_name: []const u8,
25434 field_name: InternPool.NullTerminatedString,
2485525435 field_name_src: LazySrcLoc,
2485625436 unresolved_union_ty: Type,
2485725437) CompileError!Air.Inst.Ref {
24858 assert(unresolved_union_ty.zigTypeTag() == .Union);
25438 const mod = sema.mod;
25439 const ip = &mod.intern_pool;
25440 assert(unresolved_union_ty.zigTypeTag(mod) == .Union);
2485925441
2486025442 const union_ty = try sema.resolveTypeFields(unresolved_union_ty);
24861 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
25443 const union_obj = mod.typeToUnion(union_ty).?;
2486225444 const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src);
2486325445 const field = union_obj.fields.values()[field_index];
24864 const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?);
25446 const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name, mod).?);
2486525447
2486625448 if (try sema.resolveMaybeUndefVal(union_byval)) |union_val| {
24867 if (union_val.isUndef()) return sema.addConstUndef(field.ty);
25449 if (union_val.isUndef(mod)) return sema.addConstUndef(field.ty);
2486825450
24869 const tag_and_val = union_val.castTag(.@"union").?.data;
24870 var field_tag_buf: Value.Payload.U32 = .{
24871 .base = .{ .tag = .enum_field_index },
24872 .data = enum_field_index,
24873 };
24874 const field_tag = Value.initPayload(&field_tag_buf.base);
24875 const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod);
25451 const un = ip.indexToKey(union_val.toIntern()).un;
25452 const field_tag = try mod.enumValueFieldIndex(union_obj.tag_ty, enum_field_index);
25453 const tag_matches = un.tag == field_tag.toIntern();
2487625454 switch (union_obj.layout) {
2487725455 .Auto => {
2487825456 if (tag_matches) {
24879 return sema.addConstant(field.ty, tag_and_val.val);
25457 return sema.addConstant(field.ty, un.val.toValue());
2488025458 } else {
2488125459 const msg = msg: {
24882 const active_index = tag_and_val.tag.castTag(.enum_field_index).?.data;
24883 const active_field_name = union_obj.tag_ty.enumFieldName(active_index);
24884 const msg = try sema.errMsg(block, src, "access of union field '{s}' while field '{s}' is active", .{ field_name, active_field_name });
25460 const active_index = union_obj.tag_ty.enumTagFieldIndex(un.tag.toValue(), mod).?;
25461 const active_field_name = union_obj.tag_ty.enumFieldName(active_index, mod);
25462 const msg = try sema.errMsg(block, src, "access of union field '{}' while field '{}' is active", .{
25463 field_name.fmt(ip), active_field_name.fmt(ip),
25464 });
2488525465 errdefer msg.destroy(sema.gpa);
2488625466 try sema.addDeclaredHereNote(msg, union_ty);
2488725467 break :msg msg;
......@@ -24891,10 +25471,10 @@ fn unionFieldVal(
2489125471 },
2489225472 .Packed, .Extern => {
2489325473 if (tag_matches) {
24894 return sema.addConstant(field.ty, tag_and_val.val);
25474 return sema.addConstant(field.ty, un.val.toValue());
2489525475 } else {
24896 const old_ty = union_ty.unionFieldType(tag_and_val.tag, sema.mod);
24897 if (try sema.bitCastVal(block, src, tag_and_val.val, old_ty, field.ty, 0)) |new_val| {
25476 const old_ty = union_ty.unionFieldType(un.tag.toValue(), mod);
25477 if (try sema.bitCastVal(block, src, un.val.toValue(), old_ty, field.ty, 0)) |new_val| {
2489825478 return sema.addConstant(field.ty, new_val);
2489925479 }
2490025480 }
......@@ -24904,14 +25484,14 @@ fn unionFieldVal(
2490425484
2490525485 try sema.requireRuntimeBlock(block, src, null);
2490625486 if (union_obj.layout == .Auto and block.wantSafety() and
24907 union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1)
25487 union_ty.unionTagTypeSafety(mod) != null and union_obj.fields.count() > 1)
2490825488 {
24909 const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index);
25489 const wanted_tag_val = try mod.enumValueFieldIndex(union_obj.tag_ty, enum_field_index);
2491025490 const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val);
2491125491 const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval);
2491225492 try sema.panicInactiveUnionField(block, active_tag, wanted_tag);
2491325493 }
24914 if (field.ty.zigTypeTag() == .NoReturn) {
25494 if (field.ty.zigTypeTag(mod) == .NoReturn) {
2491525495 _ = try block.addNoOp(.unreach);
2491625496 return Air.Inst.Ref.unreachable_value;
2491725497 }
......@@ -24928,22 +25508,22 @@ fn elemPtr(
2492825508 init: bool,
2492925509 oob_safety: bool,
2493025510) CompileError!Air.Inst.Ref {
25511 const mod = sema.mod;
2493125512 const indexable_ptr_src = src; // TODO better source location
2493225513 const indexable_ptr_ty = sema.typeOf(indexable_ptr);
24933 const target = sema.mod.getTarget();
2493425514
24935 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag()) {
24936 .Pointer => indexable_ptr_ty.elemType(),
24937 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(sema.mod)}),
25515 const indexable_ty = switch (indexable_ptr_ty.zigTypeTag(mod)) {
25516 .Pointer => indexable_ptr_ty.childType(mod),
25517 else => return sema.fail(block, indexable_ptr_src, "expected pointer, found '{}'", .{indexable_ptr_ty.fmt(mod)}),
2493825518 };
2493925519 try checkIndexable(sema, block, src, indexable_ty);
2494025520
24941 switch (indexable_ty.zigTypeTag()) {
25521 switch (indexable_ty.zigTypeTag(mod)) {
2494225522 .Array, .Vector => return sema.elemPtrArray(block, src, indexable_ptr_src, indexable_ptr, elem_index_src, elem_index, init, oob_safety),
2494325523 .Struct => {
2494425524 // Tuple field access.
2494525525 const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known");
24946 const index = @intCast(u32, index_val.toUnsignedInt(target));
25526 const index = @intCast(u32, index_val.toUnsignedInt(mod));
2494725527 return sema.tupleFieldPtr(block, src, indexable_ptr, elem_index_src, index, init);
2494825528 },
2494925529 else => {
......@@ -24966,11 +25546,11 @@ fn elemPtrOneLayerOnly(
2496625546) CompileError!Air.Inst.Ref {
2496725547 const indexable_src = src; // TODO better source location
2496825548 const indexable_ty = sema.typeOf(indexable);
24969 const target = sema.mod.getTarget();
25549 const mod = sema.mod;
2497025550
2497125551 try checkIndexable(sema, block, src, indexable_ty);
2497225552
24973 switch (indexable_ty.ptrSize()) {
25553 switch (indexable_ty.ptrSize(mod)) {
2497425554 .Slice => return sema.elemPtrSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
2497525555 .Many, .C => {
2497625556 const maybe_ptr_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
......@@ -24978,9 +25558,9 @@ fn elemPtrOneLayerOnly(
2497825558 const runtime_src = rs: {
2497925559 const ptr_val = maybe_ptr_val orelse break :rs indexable_src;
2498025560 const index_val = maybe_index_val orelse break :rs elem_index_src;
24981 const index = @intCast(usize, index_val.toUnsignedInt(target));
24982 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);
25561 const index = @intCast(usize, index_val.toUnsignedInt(mod));
2498325562 const result_ty = try sema.elemPtrType(indexable_ty, index);
25563 const elem_ptr = try ptr_val.elemPtr(result_ty, index, mod);
2498425564 return sema.addConstant(result_ty, elem_ptr);
2498525565 };
2498625566 const result_ty = try sema.elemPtrType(indexable_ty, null);
......@@ -24989,7 +25569,7 @@ fn elemPtrOneLayerOnly(
2498925569 return block.addPtrElemPtr(indexable, elem_index, result_ty);
2499025570 },
2499125571 .One => {
24992 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable
25572 assert(indexable_ty.childType(mod).zigTypeTag(mod) == .Array); // Guaranteed by checkIndexable
2499325573 return sema.elemPtrArray(block, src, indexable_src, indexable, elem_index_src, elem_index, init, oob_safety);
2499425574 },
2499525575 }
......@@ -25006,7 +25586,7 @@ fn elemVal(
2500625586) CompileError!Air.Inst.Ref {
2500725587 const indexable_src = src; // TODO better source location
2500825588 const indexable_ty = sema.typeOf(indexable);
25009 const target = sema.mod.getTarget();
25589 const mod = sema.mod;
2501025590
2501125591 try checkIndexable(sema, block, src, indexable_ty);
2501225592
......@@ -25014,8 +25594,8 @@ fn elemVal(
2501425594 // index is a scalar or vector instead of unconditionally casting to usize.
2501525595 const elem_index = try sema.coerce(block, Type.usize, elem_index_uncasted, elem_index_src);
2501625596
25017 switch (indexable_ty.zigTypeTag()) {
25018 .Pointer => switch (indexable_ty.ptrSize()) {
25597 switch (indexable_ty.zigTypeTag(mod)) {
25598 .Pointer => switch (indexable_ty.ptrSize(mod)) {
2501925599 .Slice => return sema.elemValSlice(block, src, indexable_src, indexable, elem_index_src, elem_index, oob_safety),
2502025600 .Many, .C => {
2502125601 const maybe_indexable_val = try sema.resolveDefinedValue(block, indexable_src, indexable);
......@@ -25024,10 +25604,14 @@ fn elemVal(
2502425604 const runtime_src = rs: {
2502525605 const indexable_val = maybe_indexable_val orelse break :rs indexable_src;
2502625606 const index_val = maybe_index_val orelse break :rs elem_index_src;
25027 const index = @intCast(usize, index_val.toUnsignedInt(target));
25028 const elem_ptr_val = try indexable_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);
25029 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, indexable_ty)) |elem_val| {
25030 return sema.addConstant(indexable_ty.elemType2(), elem_val);
25607 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25608 const elem_ty = indexable_ty.elemType2(mod);
25609 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
25610 const many_ptr_val = try mod.getCoerced(indexable_val, many_ptr_ty);
25611 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
25612 const elem_ptr_val = try many_ptr_val.elemPtr(elem_ptr_ty, index, mod);
25613 if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
25614 return sema.addConstant(elem_ty, try mod.getCoerced(elem_val, elem_ty));
2503125615 }
2503225616 break :rs indexable_src;
2503325617 };
......@@ -25036,7 +25620,19 @@ fn elemVal(
2503625620 return block.addBinOp(.ptr_elem_val, indexable, elem_index);
2503725621 },
2503825622 .One => {
25039 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by checkIndexable
25623 const array_ty = indexable_ty.childType(mod); // Guaranteed by checkIndexable
25624 assert(array_ty.zigTypeTag(mod) == .Array);
25625
25626 if (array_ty.sentinel(mod)) |sentinel| {
25627 // index must be defined since it can access out of bounds
25628 if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| {
25629 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25630 if (index == array_ty.arrayLen(mod)) {
25631 return sema.addConstant(array_ty.childType(mod), sentinel);
25632 }
25633 }
25634 }
25635
2504025636 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, oob_safety);
2504125637 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
2504225638 },
......@@ -25049,7 +25645,7 @@ fn elemVal(
2504925645 .Struct => {
2505025646 // Tuple field access.
2505125647 const index_val = try sema.resolveConstValue(block, elem_index_src, elem_index, "tuple field access index must be comptime-known");
25052 const index = @intCast(u32, index_val.toUnsignedInt(target));
25648 const index = @intCast(u32, index_val.toUnsignedInt(mod));
2505325649 return sema.tupleField(block, indexable_src, indexable, elem_index_src, index);
2505425650 },
2505525651 else => unreachable,
......@@ -25064,6 +25660,7 @@ fn validateRuntimeElemAccess(
2506425660 parent_ty: Type,
2506525661 parent_src: LazySrcLoc,
2506625662) CompileError!void {
25663 const mod = sema.mod;
2506725664 const valid_rt = try sema.validateRunTimeType(elem_ty, false);
2506825665 if (!valid_rt) {
2506925666 const msg = msg: {
......@@ -25071,12 +25668,12 @@ fn validateRuntimeElemAccess(
2507125668 block,
2507225669 elem_index_src,
2507325670 "values of type '{}' must be comptime-known, but index value is runtime-known",
25074 .{parent_ty.fmt(sema.mod)},
25671 .{parent_ty.fmt(mod)},
2507525672 );
2507625673 errdefer msg.destroy(sema.gpa);
2507725674
25078 const src_decl = sema.mod.declPtr(block.src_decl);
25079 try sema.explainWhyTypeIsComptime(msg, parent_src.toSrcLoc(src_decl), parent_ty);
25675 const src_decl = mod.declPtr(block.src_decl);
25676 try sema.explainWhyTypeIsComptime(msg, parent_src.toSrcLoc(src_decl, mod), parent_ty);
2508025677
2508125678 break :msg msg;
2508225679 };
......@@ -25093,10 +25690,11 @@ fn tupleFieldPtr(
2509325690 field_index: u32,
2509425691 init: bool,
2509525692) CompileError!Air.Inst.Ref {
25693 const mod = sema.mod;
2509625694 const tuple_ptr_ty = sema.typeOf(tuple_ptr);
25097 const tuple_ty = tuple_ptr_ty.childType();
25695 const tuple_ty = tuple_ptr_ty.childType(mod);
2509825696 _ = try sema.resolveTypeFields(tuple_ty);
25099 const field_count = tuple_ty.structFieldCount();
25697 const field_count = tuple_ty.structFieldCount(mod);
2510025698
2510125699 if (field_count == 0) {
2510225700 return sema.fail(block, tuple_ptr_src, "indexing into empty tuple is not allowed", .{});
......@@ -25108,31 +25706,29 @@ fn tupleFieldPtr(
2510825706 });
2510925707 }
2511025708
25111 const field_ty = tuple_ty.structFieldType(field_index);
25112 const ptr_field_ty = try Type.ptr(sema.arena, sema.mod, .{
25709 const field_ty = tuple_ty.structFieldType(field_index, mod);
25710 const ptr_field_ty = try Type.ptr(sema.arena, mod, .{
2511325711 .pointee_type = field_ty,
25114 .mutable = tuple_ptr_ty.ptrIsMutable(),
25115 .@"volatile" = tuple_ptr_ty.isVolatilePtr(),
25116 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(),
25712 .mutable = tuple_ptr_ty.ptrIsMutable(mod),
25713 .@"volatile" = tuple_ptr_ty.isVolatilePtr(mod),
25714 .@"addrspace" = tuple_ptr_ty.ptrAddressSpace(mod),
2511725715 });
2511825716
25119 if (tuple_ty.structFieldValueComptime(field_index)) |default_val| {
25120 const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
25121 .field_ty = field_ty,
25122 .field_val = default_val,
25123 });
25124 return sema.addConstant(ptr_field_ty, val);
25717 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
25718 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25719 .ty = ptr_field_ty.toIntern(),
25720 .addr = .{ .comptime_field = default_val.toIntern() },
25721 } })).toValue());
2512525722 }
2512625723
2512725724 if (try sema.resolveMaybeUndefVal(tuple_ptr)) |tuple_ptr_val| {
25128 return sema.addConstant(
25129 ptr_field_ty,
25130 try Value.Tag.field_ptr.create(sema.arena, .{
25131 .container_ptr = tuple_ptr_val,
25132 .container_ty = tuple_ty,
25133 .field_index = field_index,
25134 }),
25135 );
25725 return sema.addConstant(ptr_field_ty, (try mod.intern(.{ .ptr = .{
25726 .ty = ptr_field_ty.toIntern(),
25727 .addr = .{ .field = .{
25728 .base = tuple_ptr_val.toIntern(),
25729 .index = field_index,
25730 } },
25731 } })).toValue());
2513625732 }
2513725733
2513825734 if (!init) {
......@@ -25151,8 +25747,9 @@ fn tupleField(
2515125747 field_index_src: LazySrcLoc,
2515225748 field_index: u32,
2515325749) CompileError!Air.Inst.Ref {
25750 const mod = sema.mod;
2515425751 const tuple_ty = try sema.resolveTypeFields(sema.typeOf(tuple));
25155 const field_count = tuple_ty.structFieldCount();
25752 const field_count = tuple_ty.structFieldCount(mod);
2515625753
2515725754 if (field_count == 0) {
2515825755 return sema.fail(block, tuple_src, "indexing into empty tuple is not allowed", .{});
......@@ -25164,15 +25761,15 @@ fn tupleField(
2516425761 });
2516525762 }
2516625763
25167 const field_ty = tuple_ty.structFieldType(field_index);
25764 const field_ty = tuple_ty.structFieldType(field_index, mod);
2516825765
25169 if (tuple_ty.structFieldValueComptime(field_index)) |default_value| {
25766 if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
2517025767 return sema.addConstant(field_ty, default_value); // comptime field
2517125768 }
2517225769
2517325770 if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
25174 if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
25175 return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, field_index));
25771 if (tuple_val.isUndef(mod)) return sema.addConstUndef(field_ty);
25772 return sema.addConstant(field_ty, try tuple_val.fieldValue(mod, field_index));
2517625773 }
2517725774
2517825775 try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
......@@ -25191,11 +25788,12 @@ fn elemValArray(
2519125788 elem_index: Air.Inst.Ref,
2519225789 oob_safety: bool,
2519325790) CompileError!Air.Inst.Ref {
25791 const mod = sema.mod;
2519425792 const array_ty = sema.typeOf(array);
25195 const array_sent = array_ty.sentinel();
25196 const array_len = array_ty.arrayLen();
25793 const array_sent = array_ty.sentinel(mod);
25794 const array_len = array_ty.arrayLen(mod);
2519725795 const array_len_s = array_len + @boolToInt(array_sent != null);
25198 const elem_ty = array_ty.childType();
25796 const elem_ty = array_ty.childType(mod);
2519925797
2520025798 if (array_len_s == 0) {
2520125799 return sema.fail(block, array_src, "indexing into empty array is not allowed", .{});
......@@ -25204,10 +25802,9 @@ fn elemValArray(
2520425802 const maybe_undef_array_val = try sema.resolveMaybeUndefVal(array);
2520525803 // index must be defined since it can access out of bounds
2520625804 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
25207 const target = sema.mod.getTarget();
2520825805
2520925806 if (maybe_index_val) |index_val| {
25210 const index = @intCast(usize, index_val.toUnsignedInt(target));
25807 const index = @intCast(usize, index_val.toUnsignedInt(mod));
2521125808 if (array_sent) |s| {
2521225809 if (index == array_len) {
2521325810 return sema.addConstant(elem_ty, s);
......@@ -25219,12 +25816,12 @@ fn elemValArray(
2521925816 }
2522025817 }
2522125818 if (maybe_undef_array_val) |array_val| {
25222 if (array_val.isUndef()) {
25819 if (array_val.isUndef(mod)) {
2522325820 return sema.addConstUndef(elem_ty);
2522425821 }
2522525822 if (maybe_index_val) |index_val| {
25226 const index = @intCast(usize, index_val.toUnsignedInt(target));
25227 const elem_val = try array_val.elemValue(sema.mod, sema.arena, index);
25823 const index = @intCast(usize, index_val.toUnsignedInt(mod));
25824 const elem_val = try array_val.elemValue(mod, index);
2522825825 return sema.addConstant(elem_ty, elem_val);
2522925826 }
2523025827 }
......@@ -25255,11 +25852,11 @@ fn elemPtrArray(
2525525852 init: bool,
2525625853 oob_safety: bool,
2525725854) CompileError!Air.Inst.Ref {
25258 const target = sema.mod.getTarget();
25855 const mod = sema.mod;
2525925856 const array_ptr_ty = sema.typeOf(array_ptr);
25260 const array_ty = array_ptr_ty.childType();
25261 const array_sent = array_ty.sentinel() != null;
25262 const array_len = array_ty.arrayLen();
25857 const array_ty = array_ptr_ty.childType(mod);
25858 const array_sent = array_ty.sentinel(mod) != null;
25859 const array_len = array_ty.arrayLen(mod);
2526325860 const array_len_s = array_len + @boolToInt(array_sent);
2526425861
2526525862 if (array_len_s == 0) {
......@@ -25269,7 +25866,7 @@ fn elemPtrArray(
2526925866 const maybe_undef_array_ptr_val = try sema.resolveMaybeUndefVal(array_ptr);
2527025867 // The index must not be undefined since it can be out of bounds.
2527125868 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {
25272 const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(target));
25869 const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(mod));
2527325870 if (index >= array_len_s) {
2527425871 const sentinel_label: []const u8 = if (array_sent) " +1 (sentinel)" else "";
2527525872 return sema.fail(block, elem_index_src, "index {d} outside array of length {d}{s}", .{ index, array_len, sentinel_label });
......@@ -25280,17 +25877,17 @@ fn elemPtrArray(
2528025877 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset);
2528125878
2528225879 if (maybe_undef_array_ptr_val) |array_ptr_val| {
25283 if (array_ptr_val.isUndef()) {
25880 if (array_ptr_val.isUndef(mod)) {
2528425881 return sema.addConstUndef(elem_ptr_ty);
2528525882 }
2528625883 if (offset) |index| {
25287 const elem_ptr = try array_ptr_val.elemPtr(array_ptr_ty, sema.arena, index, sema.mod);
25884 const elem_ptr = try array_ptr_val.elemPtr(elem_ptr_ty, index, mod);
2528825885 return sema.addConstant(elem_ptr_ty, elem_ptr);
2528925886 }
2529025887 }
2529125888
2529225889 if (!init) {
25293 try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(), array_ty, array_ptr_src);
25890 try sema.validateRuntimeElemAccess(block, elem_index_src, array_ty.elemType2(mod), array_ty, array_ptr_src);
2529425891 }
2529525892
2529625893 const runtime_src = if (maybe_undef_array_ptr_val != null) elem_index_src else array_ptr_src;
......@@ -25316,32 +25913,33 @@ fn elemValSlice(
2531625913 elem_index: Air.Inst.Ref,
2531725914 oob_safety: bool,
2531825915) CompileError!Air.Inst.Ref {
25916 const mod = sema.mod;
2531925917 const slice_ty = sema.typeOf(slice);
25320 const slice_sent = slice_ty.sentinel() != null;
25321 const elem_ty = slice_ty.elemType2();
25918 const slice_sent = slice_ty.sentinel(mod) != null;
25919 const elem_ty = slice_ty.elemType2(mod);
2532225920 var runtime_src = slice_src;
2532325921
2532425922 // slice must be defined since it can dereferenced as null
2532525923 const maybe_slice_val = try sema.resolveDefinedValue(block, slice_src, slice);
2532625924 // index must be defined since it can index out of bounds
2532725925 const maybe_index_val = try sema.resolveDefinedValue(block, elem_index_src, elem_index);
25328 const target = sema.mod.getTarget();
2532925926
2533025927 if (maybe_slice_val) |slice_val| {
2533125928 runtime_src = elem_index_src;
25332 const slice_len = slice_val.sliceLen(sema.mod);
25929 const slice_len = slice_val.sliceLen(mod);
2533325930 const slice_len_s = slice_len + @boolToInt(slice_sent);
2533425931 if (slice_len_s == 0) {
2533525932 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
2533625933 }
2533725934 if (maybe_index_val) |index_val| {
25338 const index = @intCast(usize, index_val.toUnsignedInt(target));
25935 const index = @intCast(usize, index_val.toUnsignedInt(mod));
2533925936 if (index >= slice_len_s) {
2534025937 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
2534125938 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
2534225939 }
25343 const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, sema.mod);
25344 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, slice_ty)) |elem_val| {
25940 const elem_ptr_ty = try sema.elemPtrType(slice_ty, index);
25941 const elem_ptr_val = try slice_val.elemPtr(elem_ptr_ty, index, mod);
25942 if (try sema.pointerDeref(block, slice_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
2534525943 return sema.addConstant(elem_ty, elem_val);
2534625944 }
2534725945 runtime_src = slice_src;
......@@ -25353,7 +25951,7 @@ fn elemValSlice(
2535325951 try sema.requireRuntimeBlock(block, src, runtime_src);
2535425952 if (oob_safety and block.wantSafety()) {
2535525953 const len_inst = if (maybe_slice_val) |slice_val|
25356 try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod))
25954 try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(mod))
2535725955 else
2535825956 try block.addTyOp(.slice_len, Type.usize, slice);
2535925957 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
......@@ -25373,24 +25971,24 @@ fn elemPtrSlice(
2537325971 elem_index: Air.Inst.Ref,
2537425972 oob_safety: bool,
2537525973) CompileError!Air.Inst.Ref {
25376 const target = sema.mod.getTarget();
25974 const mod = sema.mod;
2537725975 const slice_ty = sema.typeOf(slice);
25378 const slice_sent = slice_ty.sentinel() != null;
25976 const slice_sent = slice_ty.sentinel(mod) != null;
2537925977
2538025978 const maybe_undef_slice_val = try sema.resolveMaybeUndefVal(slice);
2538125979 // The index must not be undefined since it can be out of bounds.
2538225980 const offset: ?usize = if (try sema.resolveDefinedValue(block, elem_index_src, elem_index)) |index_val| o: {
25383 const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(target));
25981 const index = try sema.usizeCast(block, elem_index_src, index_val.toUnsignedInt(mod));
2538425982 break :o index;
2538525983 } else null;
2538625984
2538725985 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset);
2538825986
2538925987 if (maybe_undef_slice_val) |slice_val| {
25390 if (slice_val.isUndef()) {
25988 if (slice_val.isUndef(mod)) {
2539125989 return sema.addConstUndef(elem_ptr_ty);
2539225990 }
25393 const slice_len = slice_val.sliceLen(sema.mod);
25991 const slice_len = slice_val.sliceLen(mod);
2539425992 const slice_len_s = slice_len + @boolToInt(slice_sent);
2539525993 if (slice_len_s == 0) {
2539625994 return sema.fail(block, slice_src, "indexing into empty slice is not allowed", .{});
......@@ -25400,7 +25998,7 @@ fn elemPtrSlice(
2540025998 const sentinel_label: []const u8 = if (slice_sent) " +1 (sentinel)" else "";
2540125999 return sema.fail(block, elem_index_src, "index {d} outside slice of length {d}{s}", .{ index, slice_len, sentinel_label });
2540226000 }
25403 const elem_ptr_val = try slice_val.elemPtr(slice_ty, sema.arena, index, sema.mod);
26001 const elem_ptr_val = try slice_val.elemPtr(elem_ptr_ty, index, mod);
2540426002 return sema.addConstant(elem_ptr_ty, elem_ptr_val);
2540526003 }
2540626004 }
......@@ -25412,8 +26010,8 @@ fn elemPtrSlice(
2541226010 if (oob_safety and block.wantSafety()) {
2541326011 const len_inst = len: {
2541426012 if (maybe_undef_slice_val) |slice_val|
25415 if (!slice_val.isUndef())
25416 break :len try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod));
26013 if (!slice_val.isUndef(mod))
26014 break :len try sema.addIntUnsigned(Type.usize, slice_val.sliceLen(mod));
2541726015 break :len try block.addTyOp(.slice_len, Type.usize, slice);
2541826016 };
2541926017 const cmp_op: Air.Inst.Tag = if (slice_sent) .cmp_lte else .cmp_lt;
......@@ -25455,16 +26053,17 @@ const CoerceOpts = struct {
2545526053
2545626054 fn get(info: @This(), sema: *Sema) !?Module.SrcLoc {
2545726055 if (info.func_inst == .none) return null;
26056 const mod = sema.mod;
2545826057 const fn_decl = (try sema.funcDeclSrc(info.func_inst)) orelse return null;
25459 const param_src = Module.paramSrc(0, sema.gpa, fn_decl, info.param_i);
26058 const param_src = Module.paramSrc(0, mod, fn_decl, info.param_i);
2546026059 if (param_src == .node_offset_param) {
2546126060 return Module.SrcLoc{
25462 .file_scope = fn_decl.getFileScope(),
26061 .file_scope = fn_decl.getFileScope(mod),
2546326062 .parent_decl_node = fn_decl.src_node,
2546426063 .lazy = LazySrcLoc.nodeOffset(param_src.node_offset_param),
2546526064 };
2546626065 }
25467 return param_src.toSrcLoc(fn_decl);
26066 return param_src.toSrcLoc(fn_decl, mod);
2546826067 }
2546926068 } = .{},
2547026069};
......@@ -25477,34 +26076,30 @@ fn coerceExtra(
2547726076 inst_src: LazySrcLoc,
2547826077 opts: CoerceOpts,
2547926078) CoersionError!Air.Inst.Ref {
25480 switch (dest_ty_unresolved.tag()) {
25481 .generic_poison => return inst,
25482 else => {},
25483 }
26079 if (dest_ty_unresolved.isGenericPoison()) return inst;
26080 const mod = sema.mod;
2548426081 const dest_ty_src = inst_src; // TODO better source location
2548526082 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
2548626083 const inst_ty = try sema.resolveTypeFields(sema.typeOf(inst));
25487 const target = sema.mod.getTarget();
26084 const target = mod.getTarget();
2548826085 // If the types are the same, we can return the operand.
25489 if (dest_ty.eql(inst_ty, sema.mod))
26086 if (dest_ty.eql(inst_ty, mod))
2549026087 return inst;
2549126088
25492 const arena = sema.arena;
2549326089 const maybe_inst_val = try sema.resolveMaybeUndefVal(inst);
2549426090
2549526091 var in_memory_result = try sema.coerceInMemoryAllowed(block, dest_ty, inst_ty, false, target, dest_ty_src, inst_src);
2549626092 if (in_memory_result == .ok) {
2549726093 if (maybe_inst_val) |val| {
25498 // Keep the comptime Value representation; take the new type.
25499 return sema.addConstant(dest_ty, val);
26094 return sema.coerceInMemory(block, val, inst_ty, dest_ty, dest_ty_src);
2550026095 }
2550126096 try sema.requireRuntimeBlock(block, inst_src, null);
2550226097 return block.addBitCast(dest_ty, inst);
2550326098 }
2550426099
25505 const is_undef = inst_ty.zigTypeTag() == .Undefined;
26100 const is_undef = inst_ty.zigTypeTag(mod) == .Undefined;
2550626101
25507 switch (dest_ty.zigTypeTag()) {
26102 switch (dest_ty.zigTypeTag(mod)) {
2550826103 .Optional => optional: {
2550926104 // undefined sets the optional bit also to undefined.
2551026105 if (is_undef) {
......@@ -25512,18 +26107,22 @@ fn coerceExtra(
2551226107 }
2551326108
2551426109 // null to ?T
25515 if (inst_ty.zigTypeTag() == .Null) {
25516 return sema.addConstant(dest_ty, Value.null);
26110 if (inst_ty.zigTypeTag(mod) == .Null) {
26111 return sema.addConstant(dest_ty, (try mod.intern(.{ .opt = .{
26112 .ty = dest_ty.toIntern(),
26113 .val = .none,
26114 } })).toValue());
2551726115 }
2551826116
2551926117 // cast from ?*T and ?[*]T to ?*anyopaque
2552026118 // but don't do it if the source type is a double pointer
25521 if (dest_ty.isPtrLikeOptional() and dest_ty.elemType2().tag() == .anyopaque and
25522 inst_ty.isPtrAtRuntime())
26119 if (dest_ty.isPtrLikeOptional(mod) and
26120 dest_ty.elemType2(mod).toIntern() == .anyopaque_type and
26121 inst_ty.isPtrAtRuntime(mod))
2552326122 anyopaque_check: {
2552426123 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :optional;
25525 const elem_ty = inst_ty.elemType2();
25526 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
26124 const elem_ty = inst_ty.elemType2(mod);
26125 if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) {
2552726126 in_memory_result = .{ .double_ptr_to_anyopaque = .{
2552826127 .actual = inst_ty,
2552926128 .wanted = dest_ty,
......@@ -25532,12 +26131,12 @@ fn coerceExtra(
2553226131 }
2553326132 // Let the logic below handle wrapping the optional now that
2553426133 // it has been checked to correctly coerce.
25535 if (!inst_ty.isPtrLikeOptional()) break :anyopaque_check;
26134 if (!inst_ty.isPtrLikeOptional(mod)) break :anyopaque_check;
2553626135 return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
2553726136 }
2553826137
2553926138 // T to ?T
25540 const child_type = try dest_ty.optionalChildAlloc(sema.arena);
26139 const child_type = dest_ty.optionalChild(mod);
2554126140 const intermediate = sema.coerceExtra(block, child_type, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {
2554226141 error.NotCoercible => {
2554326142 if (in_memory_result == .no_match) {
......@@ -25551,12 +26150,12 @@ fn coerceExtra(
2555126150 return try sema.wrapOptional(block, dest_ty, intermediate, inst_src);
2555226151 },
2555326152 .Pointer => pointer: {
25554 const dest_info = dest_ty.ptrInfo().data;
26153 const dest_info = dest_ty.ptrInfo(mod);
2555526154
2555626155 // Function body to function pointer.
25557 if (inst_ty.zigTypeTag() == .Fn) {
26156 if (inst_ty.zigTypeTag(mod) == .Fn) {
2555826157 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
25559 const fn_decl = fn_val.pointerDecl().?;
26158 const fn_decl = fn_val.pointerDecl(mod).?;
2556026159 const inst_as_ptr = try sema.analyzeDeclRef(fn_decl);
2556126160 return sema.coerce(block, dest_ty, inst_as_ptr, inst_src);
2556226161 }
......@@ -25564,13 +26163,13 @@ fn coerceExtra(
2556426163 // *T to *[1]T
2556526164 single_item: {
2556626165 if (dest_info.size != .One) break :single_item;
25567 if (!inst_ty.isSinglePointer()) break :single_item;
26166 if (!inst_ty.isSinglePointer(mod)) break :single_item;
2556826167 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
25569 const ptr_elem_ty = inst_ty.childType();
26168 const ptr_elem_ty = inst_ty.childType(mod);
2557026169 const array_ty = dest_info.pointee_type;
25571 if (array_ty.zigTypeTag() != .Array) break :single_item;
25572 const array_elem_ty = array_ty.childType();
25573 if (array_ty.arrayLen() != 1) break :single_item;
26170 if (array_ty.zigTypeTag(mod) != .Array) break :single_item;
26171 const array_elem_ty = array_ty.childType(mod);
26172 if (array_ty.arrayLen(mod) != 1) break :single_item;
2557426173 const dest_is_mut = dest_info.mutable;
2557526174 switch (try sema.coerceInMemoryAllowed(block, array_elem_ty, ptr_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
2557626175 .ok => {},
......@@ -25581,11 +26180,11 @@ fn coerceExtra(
2558126180
2558226181 // Coercions where the source is a single pointer to an array.
2558326182 src_array_ptr: {
25584 if (!inst_ty.isSinglePointer()) break :src_array_ptr;
26183 if (!inst_ty.isSinglePointer(mod)) break :src_array_ptr;
2558526184 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
25586 const array_ty = inst_ty.childType();
25587 if (array_ty.zigTypeTag() != .Array) break :src_array_ptr;
25588 const array_elem_type = array_ty.childType();
26185 const array_ty = inst_ty.childType(mod);
26186 if (array_ty.zigTypeTag(mod) != .Array) break :src_array_ptr;
26187 const array_elem_type = array_ty.childType(mod);
2558926188 const dest_is_mut = dest_info.mutable;
2559026189
2559126190 const dst_elem_type = dest_info.pointee_type;
......@@ -25603,8 +26202,8 @@ fn coerceExtra(
2560326202 }
2560426203
2560526204 if (dest_info.sentinel) |dest_sent| {
25606 if (array_ty.sentinel()) |inst_sent| {
25607 if (!dest_sent.eql(inst_sent, dst_elem_type, sema.mod)) {
26205 if (array_ty.sentinel(mod)) |inst_sent| {
26206 if (!dest_sent.eql(inst_sent, dst_elem_type, mod)) {
2560826207 in_memory_result = .{ .ptr_sentinel = .{
2560926208 .actual = inst_sent,
2561026209 .wanted = dest_sent,
......@@ -25614,7 +26213,7 @@ fn coerceExtra(
2561426213 }
2561526214 } else {
2561626215 in_memory_result = .{ .ptr_sentinel = .{
25617 .actual = Value.initTag(.unreachable_value),
26216 .actual = Value.@"unreachable",
2561826217 .wanted = dest_sent,
2561926218 .ty = dst_elem_type,
2562026219 } };
......@@ -25640,11 +26239,11 @@ fn coerceExtra(
2564026239 }
2564126240
2564226241 // coercion from C pointer
25643 if (inst_ty.isCPtr()) src_c_ptr: {
26242 if (inst_ty.isCPtr(mod)) src_c_ptr: {
2564426243 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :src_c_ptr;
2564526244 // In this case we must add a safety check because the C pointer
2564626245 // could be null.
25647 const src_elem_ty = inst_ty.childType();
26246 const src_elem_ty = inst_ty.childType(mod);
2564826247 const dest_is_mut = dest_info.mutable;
2564926248 const dst_elem_type = dest_info.pointee_type;
2565026249 switch (try sema.coerceInMemoryAllowed(block, dst_elem_type, src_elem_ty, dest_is_mut, target, dest_ty_src, inst_src)) {
......@@ -25656,18 +26255,18 @@ fn coerceExtra(
2565626255
2565726256 // cast from *T and [*]T to *anyopaque
2565826257 // but don't do it if the source type is a double pointer
25659 if (dest_info.pointee_type.tag() == .anyopaque and inst_ty.zigTypeTag() == .Pointer) to_anyopaque: {
26258 if (dest_info.pointee_type.toIntern() == .anyopaque_type and inst_ty.zigTypeTag(mod) == .Pointer) to_anyopaque: {
2566026259 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :pointer;
25661 const elem_ty = inst_ty.elemType2();
25662 if (elem_ty.zigTypeTag() == .Pointer or elem_ty.isPtrLikeOptional()) {
26260 const elem_ty = inst_ty.elemType2(mod);
26261 if (elem_ty.zigTypeTag(mod) == .Pointer or elem_ty.isPtrLikeOptional(mod)) {
2566326262 in_memory_result = .{ .double_ptr_to_anyopaque = .{
2566426263 .actual = inst_ty,
2566526264 .wanted = dest_ty,
2566626265 } };
2566726266 break :pointer;
2566826267 }
25669 if (dest_ty.isSlice()) break :to_anyopaque;
25670 if (inst_ty.isSlice()) {
26268 if (dest_ty.isSlice(mod)) break :to_anyopaque;
26269 if (inst_ty.isSlice(mod)) {
2567126270 in_memory_result = .{ .slice_to_anyopaque = .{
2567226271 .actual = inst_ty,
2567326272 .wanted = dest_ty,
......@@ -25679,9 +26278,9 @@ fn coerceExtra(
2567926278
2568026279 switch (dest_info.size) {
2568126280 // coercion to C pointer
25682 .C => switch (inst_ty.zigTypeTag()) {
26281 .C => switch (inst_ty.zigTypeTag(mod)) {
2568326282 .Null => {
25684 return sema.addConstant(dest_ty, Value.null);
26283 return sema.addConstant(dest_ty, try mod.getCoerced(Value.null, dest_ty));
2568526284 },
2568626285 .ComptimeInt => {
2568726286 const addr = sema.coerceExtra(block, Type.usize, inst, inst_src, .{ .report_err = false }) catch |err| switch (err) {
......@@ -25691,7 +26290,7 @@ fn coerceExtra(
2569126290 return try sema.coerceCompatiblePtrs(block, dest_ty, addr, inst_src);
2569226291 },
2569326292 .Int => {
25694 const ptr_size_ty = switch (inst_ty.intInfo(target).signedness) {
26293 const ptr_size_ty = switch (inst_ty.intInfo(mod).signedness) {
2569526294 .signed => Type.isize,
2569626295 .unsigned => Type.usize,
2569726296 };
......@@ -25707,7 +26306,7 @@ fn coerceExtra(
2570726306 },
2570826307 .Pointer => p: {
2570926308 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;
25710 const inst_info = inst_ty.ptrInfo().data;
26309 const inst_info = inst_ty.ptrInfo(mod);
2571126310 switch (try sema.coerceInMemoryAllowed(
2571226311 block,
2571326312 dest_info.pointee_type,
......@@ -25723,7 +26322,7 @@ fn coerceExtra(
2572326322 if (inst_info.size == .Slice) {
2572426323 assert(dest_info.sentinel == null);
2572526324 if (inst_info.sentinel == null or
25726 !inst_info.sentinel.?.eql(Value.zero, dest_info.pointee_type, sema.mod))
26325 !inst_info.sentinel.?.eql(try mod.intValue(dest_info.pointee_type, 0), dest_info.pointee_type, mod))
2572726326 break :p;
2572826327
2572926328 const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
......@@ -25733,11 +26332,11 @@ fn coerceExtra(
2573326332 },
2573426333 else => {},
2573526334 },
25736 .One => switch (dest_info.pointee_type.zigTypeTag()) {
26335 .One => switch (dest_info.pointee_type.zigTypeTag(mod)) {
2573726336 .Union => {
2573826337 // pointer to anonymous struct to pointer to union
25739 if (inst_ty.isSinglePointer() and
25740 inst_ty.childType().isAnonStruct() and
26338 if (inst_ty.isSinglePointer(mod) and
26339 inst_ty.childType(mod).isAnonStruct(mod) and
2574126340 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2574226341 {
2574326342 return sema.coerceAnonStructToUnionPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
......@@ -25745,8 +26344,8 @@ fn coerceExtra(
2574526344 },
2574626345 .Struct => {
2574726346 // pointer to anonymous struct to pointer to struct
25748 if (inst_ty.isSinglePointer() and
25749 inst_ty.childType().isAnonStruct() and
26347 if (inst_ty.isSinglePointer(mod) and
26348 inst_ty.childType(mod).isAnonStruct(mod) and
2575026349 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2575126350 {
2575226351 return sema.coerceAnonStructToStructPtrs(block, dest_ty, dest_ty_src, inst, inst_src) catch |err| switch (err) {
......@@ -25757,8 +26356,8 @@ fn coerceExtra(
2575726356 },
2575826357 .Array => {
2575926358 // pointer to tuple to pointer to array
25760 if (inst_ty.isSinglePointer() and
25761 inst_ty.childType().isTuple() and
26359 if (inst_ty.isSinglePointer(mod) and
26360 inst_ty.childType(mod).isTuple(mod) and
2576226361 sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result))
2576326362 {
2576426363 return sema.coerceTupleToArrayPtrs(block, dest_ty, dest_ty_src, inst, inst_src);
......@@ -25767,38 +26366,38 @@ fn coerceExtra(
2576726366 else => {},
2576826367 },
2576926368 .Slice => to_slice: {
25770 if (inst_ty.zigTypeTag() == .Array) {
26369 if (inst_ty.zigTypeTag(mod) == .Array) {
2577126370 return sema.fail(
2577226371 block,
2577326372 inst_src,
2577426373 "array literal requires address-of operator (&) to coerce to slice type '{}'",
25775 .{dest_ty.fmt(sema.mod)},
26374 .{dest_ty.fmt(mod)},
2577626375 );
2577726376 }
2577826377
25779 if (!inst_ty.isSinglePointer()) break :to_slice;
25780 const inst_child_ty = inst_ty.childType();
25781 if (!inst_child_ty.isTuple()) break :to_slice;
26378 if (!inst_ty.isSinglePointer(mod)) break :to_slice;
26379 const inst_child_ty = inst_ty.childType(mod);
26380 if (!inst_child_ty.isTuple(mod)) break :to_slice;
2578226381
2578326382 // empty tuple to zero-length slice
2578426383 // note that this allows coercing to a mutable slice.
25785 if (inst_child_ty.structFieldCount() == 0) {
26384 if (inst_child_ty.structFieldCount(mod) == 0) {
2578626385 // Optional slice is represented with a null pointer so
2578726386 // we use a dummy pointer value with the required alignment.
25788 const slice_val = try Value.Tag.slice.create(sema.arena, .{
25789 .ptr = if (dest_info.@"align" != 0)
25790 try Value.Tag.int_u64.create(sema.arena, dest_info.@"align")
26387 return sema.addConstant(dest_ty, (try mod.intern(.{ .ptr = .{
26388 .ty = dest_ty.toIntern(),
26389 .addr = .{ .int = (if (dest_info.@"align" != 0)
26390 try mod.intValue(Type.usize, dest_info.@"align")
2579126391 else
25792 try dest_info.pointee_type.lazyAbiAlignment(target, sema.arena),
25793 .len = Value.zero,
25794 });
25795 return sema.addConstant(dest_ty, slice_val);
26392 try mod.getCoerced(try dest_info.pointee_type.lazyAbiAlignment(mod), Type.usize)).toIntern() },
26393 .len = (try mod.intValue(Type.usize, 0)).toIntern(),
26394 } })).toValue());
2579626395 }
2579726396
2579826397 // pointer to tuple to slice
2579926398 if (dest_info.mutable) {
2580026399 const err_msg = err_msg: {
25801 const err_msg = try sema.errMsg(block, inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(sema.mod)});
26400 const err_msg = try sema.errMsg(block, inst_src, "cannot cast pointer to tuple to '{}'", .{dest_ty.fmt(mod)});
2580226401 errdefer err_msg.deinit(sema.gpa);
2580326402 try sema.errNote(block, dest_ty_src, err_msg, "pointers to tuples can only coerce to constant pointers", .{});
2580426403 break :err_msg err_msg;
......@@ -25808,9 +26407,9 @@ fn coerceExtra(
2580826407 return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src);
2580926408 },
2581026409 .Many => p: {
25811 if (!inst_ty.isSlice()) break :p;
26410 if (!inst_ty.isSlice(mod)) break :p;
2581226411 if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p;
25813 const inst_info = inst_ty.ptrInfo().data;
26412 const inst_info = inst_ty.ptrInfo(mod);
2581426413
2581526414 switch (try sema.coerceInMemoryAllowed(
2581626415 block,
......@@ -25826,7 +26425,11 @@ fn coerceExtra(
2582626425 }
2582726426
2582826427 if (dest_info.sentinel == null or inst_info.sentinel == null or
25829 !dest_info.sentinel.?.eql(inst_info.sentinel.?, dest_info.pointee_type, sema.mod))
26428 !dest_info.sentinel.?.eql(
26429 try mod.getCoerced(inst_info.sentinel.?, dest_info.pointee_type),
26430 dest_info.pointee_type,
26431 mod,
26432 ))
2583026433 break :p;
2583126434
2583226435 const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
......@@ -25834,25 +26437,25 @@ fn coerceExtra(
2583426437 },
2583526438 }
2583626439 },
25837 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag()) {
26440 .Int, .ComptimeInt => switch (inst_ty.zigTypeTag(mod)) {
2583826441 .Float, .ComptimeFloat => float: {
2583926442 if (is_undef) {
2584026443 return sema.addConstUndef(dest_ty);
2584126444 }
2584226445 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
25843 if (dest_ty.zigTypeTag() == .ComptimeInt) {
26446 if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {
2584426447 if (!opts.report_err) return error.NotCoercible;
2584526448 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");
2584626449 }
2584726450 break :float;
2584826451 };
2584926452
25850 if (val.floatHasFraction()) {
26453 if (val.floatHasFraction(mod)) {
2585126454 return sema.fail(
2585226455 block,
2585326456 inst_src,
2585426457 "fractional component prevents float value '{}' from coercion to type '{}'",
25855 .{ val.fmtValue(inst_ty, sema.mod), dest_ty.fmt(sema.mod) },
26458 .{ val.fmtValue(inst_ty, mod), dest_ty.fmt(mod) },
2585626459 );
2585726460 }
2585826461 const result_val = try sema.floatToInt(block, inst_src, val, inst_ty, dest_ty);
......@@ -25866,19 +26469,19 @@ fn coerceExtra(
2586626469 // comptime-known integer to other number
2586726470 if (!(try sema.intFitsInType(val, dest_ty, null))) {
2586826471 if (!opts.report_err) return error.NotCoercible;
25869 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) });
26472 return sema.fail(block, inst_src, "type '{}' cannot represent integer value '{}'", .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) });
2587026473 }
25871 return try sema.addConstant(dest_ty, val);
26474 return try sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
2587226475 }
25873 if (dest_ty.zigTypeTag() == .ComptimeInt) {
26476 if (dest_ty.zigTypeTag(mod) == .ComptimeInt) {
2587426477 if (!opts.report_err) return error.NotCoercible;
2587526478 if (opts.no_cast_to_comptime_int) return inst;
2587626479 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_int' must be comptime-known");
2587726480 }
2587826481
2587926482 // integer widening
25880 const dst_info = dest_ty.intInfo(target);
25881 const src_info = inst_ty.intInfo(target);
26483 const dst_info = dest_ty.intInfo(mod);
26484 const src_info = inst_ty.intInfo(mod);
2588226485 if ((src_info.signedness == dst_info.signedness and dst_info.bits >= src_info.bits) or
2588326486 // small enough unsigned ints can get casted to large enough signed ints
2588426487 (dst_info.signedness == .signed and dst_info.bits > src_info.bits))
......@@ -25892,10 +26495,10 @@ fn coerceExtra(
2589226495 },
2589326496 else => {},
2589426497 },
25895 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag()) {
26498 .Float, .ComptimeFloat => switch (inst_ty.zigTypeTag(mod)) {
2589626499 .ComptimeFloat => {
2589726500 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
25898 const result_val = try val.floatCast(sema.arena, dest_ty, target);
26501 const result_val = try val.floatCast(dest_ty, mod);
2589926502 return try sema.addConstant(dest_ty, result_val);
2590026503 },
2590126504 .Float => {
......@@ -25903,17 +26506,17 @@ fn coerceExtra(
2590326506 return sema.addConstUndef(dest_ty);
2590426507 }
2590526508 if (try sema.resolveMaybeUndefVal(inst)) |val| {
25906 const result_val = try val.floatCast(sema.arena, dest_ty, target);
25907 if (!val.eql(result_val, inst_ty, sema.mod)) {
26509 const result_val = try val.floatCast(dest_ty, mod);
26510 if (!val.eql(try result_val.floatCast(inst_ty, mod), inst_ty, mod)) {
2590826511 return sema.fail(
2590926512 block,
2591026513 inst_src,
2591126514 "type '{}' cannot represent float value '{}'",
25912 .{ dest_ty.fmt(sema.mod), val.fmtValue(inst_ty, sema.mod) },
26515 .{ dest_ty.fmt(mod), val.fmtValue(inst_ty, mod) },
2591326516 );
2591426517 }
2591526518 return try sema.addConstant(dest_ty, result_val);
25916 } else if (dest_ty.zigTypeTag() == .ComptimeFloat) {
26519 } else if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) {
2591726520 if (!opts.report_err) return error.NotCoercible;
2591826521 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");
2591926522 }
......@@ -25931,13 +26534,13 @@ fn coerceExtra(
2593126534 return sema.addConstUndef(dest_ty);
2593226535 }
2593326536 const val = (try sema.resolveMaybeUndefVal(inst)) orelse {
25934 if (dest_ty.zigTypeTag() == .ComptimeFloat) {
26537 if (dest_ty.zigTypeTag(mod) == .ComptimeFloat) {
2593526538 if (!opts.report_err) return error.NotCoercible;
2593626539 return sema.failWithNeededComptime(block, inst_src, "value being casted to 'comptime_float' must be comptime-known");
2593726540 }
2593826541 break :int;
2593926542 };
25940 const result_val = try val.intToFloatAdvanced(sema.arena, inst_ty, dest_ty, sema.mod, sema);
26543 const result_val = try val.intToFloatAdvanced(sema.arena, inst_ty, dest_ty, mod, sema);
2594126544 // TODO implement this compile error
2594226545 //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty);
2594326546 //if (!int_again_val.eql(val, inst_ty, mod)) {
......@@ -25945,7 +26548,7 @@ fn coerceExtra(
2594526548 // block,
2594626549 // inst_src,
2594726550 // "type '{}' cannot represent integer value '{}'",
25948 // .{ dest_ty.fmt(sema.mod), val },
26551 // .{ dest_ty.fmt(mod), val },
2594926552 // );
2595026553 //}
2595126554 return try sema.addConstant(dest_ty, result_val);
......@@ -25955,18 +26558,18 @@ fn coerceExtra(
2595526558 },
2595626559 else => {},
2595726560 },
25958 .Enum => switch (inst_ty.zigTypeTag()) {
26561 .Enum => switch (inst_ty.zigTypeTag(mod)) {
2595926562 .EnumLiteral => {
2596026563 // enum literal to enum
2596126564 const val = try sema.resolveConstValue(block, .unneeded, inst, "");
25962 const bytes = val.castTag(.enum_literal).?.data;
25963 const field_index = dest_ty.enumFieldIndex(bytes) orelse {
26565 const string = mod.intern_pool.indexToKey(val.toIntern()).enum_literal;
26566 const field_index = dest_ty.enumFieldIndex(string, mod) orelse {
2596426567 const msg = msg: {
2596526568 const msg = try sema.errMsg(
2596626569 block,
2596726570 inst_src,
25968 "no field named '{s}' in enum '{}'",
25969 .{ bytes, dest_ty.fmt(sema.mod) },
26571 "no field named '{}' in enum '{}'",
26572 .{ string.fmt(&mod.intern_pool), dest_ty.fmt(mod) },
2597026573 );
2597126574 errdefer msg.destroy(sema.gpa);
2597226575 try sema.addDeclaredHereNote(msg, dest_ty);
......@@ -25976,13 +26579,13 @@ fn coerceExtra(
2597626579 };
2597726580 return sema.addConstant(
2597826581 dest_ty,
25979 try Value.Tag.enum_field_index.create(arena, @intCast(u32, field_index)),
26582 try mod.enumValueFieldIndex(dest_ty, @intCast(u32, field_index)),
2598026583 );
2598126584 },
2598226585 .Union => blk: {
2598326586 // union to its own tag type
25984 const union_tag_ty = inst_ty.unionTagType() orelse break :blk;
25985 if (union_tag_ty.eql(dest_ty, sema.mod)) {
26587 const union_tag_ty = inst_ty.unionTagType(mod) orelse break :blk;
26588 if (union_tag_ty.eql(dest_ty, mod)) {
2598626589 return sema.unionToTag(block, dest_ty, inst, inst_src);
2598726590 }
2598826591 },
......@@ -25991,27 +26594,33 @@ fn coerceExtra(
2599126594 },
2599226595 else => {},
2599326596 },
25994 .ErrorUnion => switch (inst_ty.zigTypeTag()) {
26597 .ErrorUnion => switch (inst_ty.zigTypeTag(mod)) {
2599526598 .ErrorUnion => eu: {
2599626599 if (maybe_inst_val) |inst_val| {
25997 switch (inst_val.tag()) {
26600 switch (inst_val.toIntern()) {
2599826601 .undef => return sema.addConstUndef(dest_ty),
25999 .eu_payload => {
26000 const payload = try sema.addConstant(
26001 inst_ty.errorUnionPayload(),
26002 inst_val.castTag(.eu_payload).?.data,
26003 );
26004 return sema.wrapErrorUnionPayload(block, dest_ty, payload, inst_src) catch |err| switch (err) {
26005 error.NotCoercible => break :eu,
26006 else => |e| return e,
26007 };
26008 },
26009 else => {
26010 const error_set = try sema.addConstant(
26011 inst_ty.errorUnionSet(),
26012 inst_val,
26013 );
26014 return sema.wrapErrorUnionSet(block, dest_ty, error_set, inst_src);
26602 else => switch (mod.intern_pool.indexToKey(inst_val.toIntern())) {
26603 .error_union => |error_union| switch (error_union.val) {
26604 .err_name => |err_name| {
26605 const error_set_ty = inst_ty.errorUnionSet(mod);
26606 const error_set_val = try sema.addConstant(error_set_ty, (try mod.intern(.{ .err = .{
26607 .ty = error_set_ty.toIntern(),
26608 .name = err_name,
26609 } })).toValue());
26610 return sema.wrapErrorUnionSet(block, dest_ty, error_set_val, inst_src);
26611 },
26612 .payload => |payload| {
26613 const payload_val = try sema.addConstant(
26614 inst_ty.errorUnionPayload(mod),
26615 payload.toValue(),
26616 );
26617 return sema.wrapErrorUnionPayload(block, dest_ty, payload_val, inst_src) catch |err| switch (err) {
26618 error.NotCoercible => break :eu,
26619 else => |e| return e,
26620 };
26621 },
26622 },
26623 else => unreachable,
2601526624 },
2601626625 }
2601726626 }
......@@ -26031,10 +26640,10 @@ fn coerceExtra(
2603126640 };
2603226641 },
2603326642 },
26034 .Union => switch (inst_ty.zigTypeTag()) {
26643 .Union => switch (inst_ty.zigTypeTag(mod)) {
2603526644 .Enum, .EnumLiteral => return sema.coerceEnumToUnion(block, dest_ty, dest_ty_src, inst, inst_src),
2603626645 .Struct => {
26037 if (inst_ty.isAnonStruct()) {
26646 if (inst_ty.isAnonStruct(mod)) {
2603826647 return sema.coerceAnonStructToUnion(block, dest_ty, dest_ty_src, inst, inst_src);
2603926648 }
2604026649 },
......@@ -26043,13 +26652,13 @@ fn coerceExtra(
2604326652 },
2604426653 else => {},
2604526654 },
26046 .Array => switch (inst_ty.zigTypeTag()) {
26655 .Array => switch (inst_ty.zigTypeTag(mod)) {
2604726656 .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
2604826657 .Struct => {
2604926658 if (inst == .empty_struct) {
2605026659 return sema.arrayInitEmpty(block, inst_src, dest_ty);
2605126660 }
26052 if (inst_ty.isTuple()) {
26661 if (inst_ty.isTuple(mod)) {
2605326662 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
2605426663 }
2605526664 },
......@@ -26058,10 +26667,10 @@ fn coerceExtra(
2605826667 },
2605926668 else => {},
2606026669 },
26061 .Vector => switch (inst_ty.zigTypeTag()) {
26670 .Vector => switch (inst_ty.zigTypeTag(mod)) {
2606226671 .Array, .Vector => return sema.coerceArrayLike(block, dest_ty, dest_ty_src, inst, inst_src),
2606326672 .Struct => {
26064 if (inst_ty.isTuple()) {
26673 if (inst_ty.isTuple(mod)) {
2606526674 return sema.coerceTupleToArray(block, dest_ty, dest_ty_src, inst, inst_src);
2606626675 }
2606726676 },
......@@ -26074,7 +26683,7 @@ fn coerceExtra(
2607426683 if (inst == .empty_struct) {
2607526684 return sema.structInitEmpty(block, dest_ty, dest_ty_src, inst_src);
2607626685 }
26077 if (inst_ty.isTupleOrAnonStruct()) {
26686 if (inst_ty.isTupleOrAnonStruct(mod)) {
2607826687 return sema.coerceTupleToStruct(block, dest_ty, inst, inst_src) catch |err| switch (err) {
2607926688 error.NotCoercible => break :blk,
2608026689 else => |e| return e,
......@@ -26093,35 +26702,34 @@ fn coerceExtra(
2609326702
2609426703 if (!opts.report_err) return error.NotCoercible;
2609526704
26096 if (opts.is_ret and dest_ty.zigTypeTag() == .NoReturn) {
26705 if (opts.is_ret and dest_ty.zigTypeTag(mod) == .NoReturn) {
2609726706 const msg = msg: {
2609826707 const msg = try sema.errMsg(block, inst_src, "function declared 'noreturn' returns", .{});
2609926708 errdefer msg.destroy(sema.gpa);
2610026709
2610126710 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
26102 const src_decl = sema.mod.declPtr(sema.func.?.owner_decl);
26103 try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "'noreturn' declared here", .{});
26711 const src_decl = mod.declPtr(sema.func.?.owner_decl);
26712 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "'noreturn' declared here", .{});
2610426713 break :msg msg;
2610526714 };
2610626715 return sema.failWithOwnedErrorMsg(msg);
2610726716 }
2610826717
2610926718 const msg = msg: {
26110 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod) });
26719 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{ dest_ty.fmt(mod), inst_ty.fmt(mod) });
2611126720 errdefer msg.destroy(sema.gpa);
2611226721
2611326722 // E!T to T
26114 if (inst_ty.zigTypeTag() == .ErrorUnion and
26115 (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
26723 if (inst_ty.zigTypeTag(mod) == .ErrorUnion and
26724 (try sema.coerceInMemoryAllowed(block, inst_ty.errorUnionPayload(mod), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
2611626725 {
2611726726 try sema.errNote(block, inst_src, msg, "cannot convert error union to payload type", .{});
2611826727 try sema.errNote(block, inst_src, msg, "consider using 'try', 'catch', or 'if'", .{});
2611926728 }
2612026729
2612126730 // ?T to T
26122 var buf: Type.Payload.ElemType = undefined;
26123 if (inst_ty.zigTypeTag() == .Optional and
26124 (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(&buf), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
26731 if (inst_ty.zigTypeTag(mod) == .Optional and
26732 (try sema.coerceInMemoryAllowed(block, inst_ty.optionalChild(mod), dest_ty, false, target, dest_ty_src, inst_src)) == .ok)
2612526733 {
2612626734 try sema.errNote(block, inst_src, msg, "cannot convert optional to payload type", .{});
2612726735 try sema.errNote(block, inst_src, msg, "consider using '.?', 'orelse', or 'if'", .{});
......@@ -26130,18 +26738,18 @@ fn coerceExtra(
2613026738 try in_memory_result.report(sema, block, inst_src, msg);
2613126739
2613226740 // Add notes about function return type
26133 if (opts.is_ret and sema.mod.test_functions.get(sema.func.?.owner_decl) == null) {
26741 if (opts.is_ret and mod.test_functions.get(sema.func.?.owner_decl) == null) {
2613426742 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
26135 const src_decl = sema.mod.declPtr(sema.func.?.owner_decl);
26136 if (inst_ty.isError() and !dest_ty.isError()) {
26137 try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function cannot return an error", .{});
26743 const src_decl = mod.declPtr(sema.func.?.owner_decl);
26744 if (inst_ty.isError(mod) and !dest_ty.isError(mod)) {
26745 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function cannot return an error", .{});
2613826746 } else {
26139 try sema.mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl), msg, "function return type declared here", .{});
26747 try mod.errNoteNonLazy(ret_ty_src.toSrcLoc(src_decl, mod), msg, "function return type declared here", .{});
2614026748 }
2614126749 }
2614226750
2614326751 if (try opts.param_src.get(sema)) |param_src| {
26144 try sema.mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{});
26752 try mod.errNoteNonLazy(param_src, msg, "parameter type declared here", .{});
2614526753 }
2614626754
2614726755 // TODO maybe add "cannot store an error in type '{}'" note
......@@ -26151,6 +26759,84 @@ fn coerceExtra(
2615126759 return sema.failWithOwnedErrorMsg(msg);
2615226760}
2615326761
26762fn coerceValueInMemory(
26763 sema: *Sema,
26764 block: *Block,
26765 val: Value,
26766 src_ty: Type,
26767 dst_ty: Type,
26768 dst_ty_src: LazySrcLoc,
26769) CompileError!Value {
26770 const mod = sema.mod;
26771 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
26772 .aggregate => |aggregate| {
26773 const dst_ty_key = mod.intern_pool.indexToKey(dst_ty.toIntern());
26774 const dest_len = try sema.usizeCast(
26775 block,
26776 dst_ty_src,
26777 mod.intern_pool.aggregateTypeLen(dst_ty.toIntern()),
26778 );
26779 direct: {
26780 const src_ty_child = switch (mod.intern_pool.indexToKey(src_ty.toIntern())) {
26781 inline .array_type, .vector_type => |seq_type| seq_type.child,
26782 .anon_struct_type, .struct_type => break :direct,
26783 else => unreachable,
26784 };
26785 const dst_ty_child = switch (dst_ty_key) {
26786 inline .array_type, .vector_type => |seq_type| seq_type.child,
26787 .anon_struct_type, .struct_type => break :direct,
26788 else => unreachable,
26789 };
26790 if (src_ty_child != dst_ty_child) break :direct;
26791 // TODO: write something like getCoercedInts to avoid needing to dupe
26792 return (try mod.intern(.{ .aggregate = .{
26793 .ty = dst_ty.toIntern(),
26794 .storage = switch (aggregate.storage) {
26795 .bytes => |bytes| .{ .bytes = try sema.arena.dupe(u8, bytes[0..dest_len]) },
26796 .elems => |elems| .{ .elems = try sema.arena.dupe(InternPool.Index, elems[0..dest_len]) },
26797 .repeated_elem => |elem| .{ .repeated_elem = elem },
26798 },
26799 } })).toValue();
26800 }
26801 const dest_elems = try sema.arena.alloc(InternPool.Index, dest_len);
26802 for (dest_elems, 0..) |*dest_elem, i| {
26803 const elem_ty = switch (dst_ty_key) {
26804 inline .array_type, .vector_type => |seq_type| seq_type.child,
26805 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i],
26806 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?
26807 .fields.values()[i].ty.toIntern(),
26808 else => unreachable,
26809 };
26810 dest_elem.* = try mod.intern_pool.getCoerced(mod.gpa, switch (aggregate.storage) {
26811 .bytes => |bytes| (try mod.intValue(Type.u8, bytes[i])).toIntern(),
26812 .elems => |elems| elems[i],
26813 .repeated_elem => |elem| elem,
26814 }, elem_ty);
26815 }
26816 return (try mod.intern(.{ .aggregate = .{
26817 .ty = dst_ty.toIntern(),
26818 .storage = .{ .elems = dest_elems },
26819 } })).toValue();
26820 },
26821 .float => |float| (try mod.intern(.{ .float = .{
26822 .ty = dst_ty.toIntern(),
26823 .storage = float.storage,
26824 } })).toValue(),
26825 else => try mod.getCoerced(val, dst_ty),
26826 };
26827}
26828
26829fn coerceInMemory(
26830 sema: *Sema,
26831 block: *Block,
26832 val: Value,
26833 src_ty: Type,
26834 dst_ty: Type,
26835 dst_ty_src: LazySrcLoc,
26836) CompileError!Air.Inst.Ref {
26837 return sema.addConstant(dst_ty, try sema.coerceValueInMemory(block, val, src_ty, dst_ty, dst_ty_src));
26838}
26839
2615426840const InMemoryCoercionResult = union(enum) {
2615526841 ok,
2615626842 no_match: Pair,
......@@ -26164,7 +26850,7 @@ const InMemoryCoercionResult = union(enum) {
2616426850 optional_shape: Pair,
2616526851 optional_child: PairAndChild,
2616626852 from_anyerror,
26167 missing_error: []const []const u8,
26853 missing_error: []const InternPool.NullTerminatedString,
2616826854 /// true if wanted is var args
2616926855 fn_var_args: bool,
2617026856 /// true if wanted is generic
......@@ -26264,6 +26950,7 @@ const InMemoryCoercionResult = union(enum) {
2626426950 }
2626526951
2626626952 fn report(res: *const InMemoryCoercionResult, sema: *Sema, block: *Block, src: LazySrcLoc, msg: *Module.ErrorMsg) !void {
26953 const mod = sema.mod;
2626726954 var cur = res;
2626826955 while (true) switch (cur.*) {
2626926956 .ok => unreachable,
......@@ -26280,7 +26967,7 @@ const InMemoryCoercionResult = union(enum) {
2628026967 },
2628126968 .error_union_payload => |pair| {
2628226969 try sema.errNote(block, src, msg, "error union payload '{}' cannot cast into error union payload '{}'", .{
26283 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
26970 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2628426971 });
2628526972 cur = pair.child;
2628626973 },
......@@ -26291,20 +26978,20 @@ const InMemoryCoercionResult = union(enum) {
2629126978 break;
2629226979 },
2629326980 .array_sentinel => |sentinel| {
26294 if (sentinel.actual.tag() != .unreachable_value) {
26981 if (sentinel.actual.toIntern() != .unreachable_value) {
2629526982 try sema.errNote(block, src, msg, "array sentinel '{}' cannot cast into array sentinel '{}'", .{
26296 sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
26983 sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod),
2629726984 });
2629826985 } else {
2629926986 try sema.errNote(block, src, msg, "destination array requires '{}' sentinel", .{
26300 sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
26987 sentinel.wanted.fmtValue(sentinel.ty, mod),
2630126988 });
2630226989 }
2630326990 break;
2630426991 },
2630526992 .array_elem => |pair| {
2630626993 try sema.errNote(block, src, msg, "array element type '{}' cannot cast into array element type '{}'", .{
26307 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
26994 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2630826995 });
2630926996 cur = pair.child;
2631026997 },
......@@ -26316,21 +27003,19 @@ const InMemoryCoercionResult = union(enum) {
2631627003 },
2631727004 .vector_elem => |pair| {
2631827005 try sema.errNote(block, src, msg, "vector element type '{}' cannot cast into vector element type '{}'", .{
26319 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27006 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2632027007 });
2632127008 cur = pair.child;
2632227009 },
2632327010 .optional_shape => |pair| {
26324 var buf_actual: Type.Payload.ElemType = undefined;
26325 var buf_wanted: Type.Payload.ElemType = undefined;
2632627011 try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{
26327 pair.actual.optionalChild(&buf_actual).fmt(sema.mod), pair.wanted.optionalChild(&buf_wanted).fmt(sema.mod),
27012 pair.actual.optionalChild(mod).fmt(mod), pair.wanted.optionalChild(mod).fmt(mod),
2632827013 });
2632927014 break;
2633027015 },
2633127016 .optional_child => |pair| {
2633227017 try sema.errNote(block, src, msg, "optional type child '{}' cannot cast into optional type child '{}'", .{
26333 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27018 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2633427019 });
2633527020 cur = pair.child;
2633627021 },
......@@ -26340,7 +27025,7 @@ const InMemoryCoercionResult = union(enum) {
2634027025 },
2634127026 .missing_error => |missing_errors| {
2634227027 for (missing_errors) |err| {
26343 try sema.errNote(block, src, msg, "'error.{s}' not a member of destination error set", .{err});
27028 try sema.errNote(block, src, msg, "'error.{}' not a member of destination error set", .{err.fmt(&mod.intern_pool)});
2634427029 }
2634527030 break;
2634627031 },
......@@ -26394,7 +27079,7 @@ const InMemoryCoercionResult = union(enum) {
2639427079 },
2639527080 .fn_param => |param| {
2639627081 try sema.errNote(block, src, msg, "parameter {d} '{}' cannot cast into '{}'", .{
26397 param.index, param.actual.fmt(sema.mod), param.wanted.fmt(sema.mod),
27082 param.index, param.actual.fmt(mod), param.wanted.fmt(mod),
2639827083 });
2639927084 cur = param.child;
2640027085 },
......@@ -26404,13 +27089,13 @@ const InMemoryCoercionResult = union(enum) {
2640427089 },
2640527090 .fn_return_type => |pair| {
2640627091 try sema.errNote(block, src, msg, "return type '{}' cannot cast into return type '{}'", .{
26407 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27092 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2640827093 });
2640927094 cur = pair.child;
2641027095 },
2641127096 .ptr_child => |pair| {
2641227097 try sema.errNote(block, src, msg, "pointer type child '{}' cannot cast into pointer type child '{}'", .{
26413 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27098 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2641427099 });
2641527100 cur = pair.child;
2641627101 },
......@@ -26419,13 +27104,13 @@ const InMemoryCoercionResult = union(enum) {
2641927104 break;
2642027105 },
2642127106 .ptr_sentinel => |sentinel| {
26422 if (sentinel.actual.tag() != .unreachable_value) {
27107 if (sentinel.actual.toIntern() != .unreachable_value) {
2642327108 try sema.errNote(block, src, msg, "pointer sentinel '{}' cannot cast into pointer sentinel '{}'", .{
26424 sentinel.actual.fmtValue(sentinel.ty, sema.mod), sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
27109 sentinel.actual.fmtValue(sentinel.ty, mod), sentinel.wanted.fmtValue(sentinel.ty, mod),
2642527110 });
2642627111 } else {
2642727112 try sema.errNote(block, src, msg, "destination pointer requires '{}' sentinel", .{
26428 sentinel.wanted.fmtValue(sentinel.ty, sema.mod),
27113 sentinel.wanted.fmtValue(sentinel.ty, mod),
2642927114 });
2643027115 }
2643127116 break;
......@@ -26445,15 +27130,15 @@ const InMemoryCoercionResult = union(enum) {
2644527130 break;
2644627131 },
2644727132 .ptr_allowzero => |pair| {
26448 const wanted_allow_zero = pair.wanted.ptrAllowsZero();
26449 const actual_allow_zero = pair.actual.ptrAllowsZero();
27133 const wanted_allow_zero = pair.wanted.ptrAllowsZero(mod);
27134 const actual_allow_zero = pair.actual.ptrAllowsZero(mod);
2645027135 if (actual_allow_zero and !wanted_allow_zero) {
2645127136 try sema.errNote(block, src, msg, "'{}' could have null values which are illegal in type '{}'", .{
26452 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27137 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2645327138 });
2645427139 } else {
2645527140 try sema.errNote(block, src, msg, "mutable '{}' allows illegal null values stored to type '{}'", .{
26456 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27141 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2645727142 });
2645827143 }
2645927144 break;
......@@ -26479,13 +27164,13 @@ const InMemoryCoercionResult = union(enum) {
2647927164 },
2648027165 .double_ptr_to_anyopaque => |pair| {
2648127166 try sema.errNote(block, src, msg, "cannot implicitly cast double pointer '{}' to anyopaque pointer '{}'", .{
26482 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27167 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2648327168 });
2648427169 break;
2648527170 },
2648627171 .slice_to_anyopaque => |pair| {
2648727172 try sema.errNote(block, src, msg, "cannot implicitly cast slice '{}' to anyopaque pointer '{}'", .{
26488 pair.actual.fmt(sema.mod), pair.wanted.fmt(sema.mod),
27173 pair.actual.fmt(mod), pair.wanted.fmt(mod),
2648927174 });
2649027175 try sema.errNote(block, src, msg, "consider using '.ptr'", .{});
2649127176 break;
......@@ -26522,13 +27207,18 @@ fn coerceInMemoryAllowed(
2652227207 dest_src: LazySrcLoc,
2652327208 src_src: LazySrcLoc,
2652427209) CompileError!InMemoryCoercionResult {
26525 if (dest_ty.eql(src_ty, sema.mod))
27210 const mod = sema.mod;
27211
27212 if (dest_ty.eql(src_ty, mod))
2652627213 return .ok;
2652727214
27215 const dest_tag = dest_ty.zigTypeTag(mod);
27216 const src_tag = src_ty.zigTypeTag(mod);
27217
2652827218 // Differently-named integers with the same number of bits.
26529 if (dest_ty.zigTypeTag() == .Int and src_ty.zigTypeTag() == .Int) {
26530 const dest_info = dest_ty.intInfo(target);
26531 const src_info = src_ty.intInfo(target);
27219 if (dest_tag == .Int and src_tag == .Int) {
27220 const dest_info = dest_ty.intInfo(mod);
27221 const src_info = src_ty.intInfo(mod);
2653227222
2653327223 if (dest_info.signedness == src_info.signedness and
2653427224 dest_info.bits == src_info.bits)
......@@ -26551,7 +27241,7 @@ fn coerceInMemoryAllowed(
2655127241 }
2655227242
2655327243 // Differently-named floats with the same number of bits.
26554 if (dest_ty.zigTypeTag() == .Float and src_ty.zigTypeTag() == .Float) {
27244 if (dest_tag == .Float and src_tag == .Float) {
2655527245 const dest_bits = dest_ty.floatBits(target);
2655627246 const src_bits = src_ty.floatBits(target);
2655727247 if (dest_bits == src_bits) {
......@@ -26560,10 +27250,8 @@ fn coerceInMemoryAllowed(
2656027250 }
2656127251
2656227252 // Pointers / Pointer-like Optionals
26563 var dest_buf: Type.Payload.ElemType = undefined;
26564 var src_buf: Type.Payload.ElemType = undefined;
26565 const maybe_dest_ptr_ty = try sema.typePtrOrOptionalPtrTy(dest_ty, &dest_buf);
26566 const maybe_src_ptr_ty = try sema.typePtrOrOptionalPtrTy(src_ty, &src_buf);
27253 const maybe_dest_ptr_ty = try sema.typePtrOrOptionalPtrTy(dest_ty);
27254 const maybe_src_ptr_ty = try sema.typePtrOrOptionalPtrTy(src_ty);
2656727255 if (maybe_dest_ptr_ty) |dest_ptr_ty| {
2656827256 if (maybe_src_ptr_ty) |src_ptr_ty| {
2656927257 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ptr_ty, src_ptr_ty, dest_is_mut, target, dest_src, src_src);
......@@ -26571,13 +27259,10 @@ fn coerceInMemoryAllowed(
2657127259 }
2657227260
2657327261 // Slices
26574 if (dest_ty.isSlice() and src_ty.isSlice()) {
27262 if (dest_ty.isSlice(mod) and src_ty.isSlice(mod)) {
2657527263 return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
2657627264 }
2657727265
26578 const dest_tag = dest_ty.zigTypeTag();
26579 const src_tag = src_ty.zigTypeTag();
26580
2658127266 // Functions
2658227267 if (dest_tag == .Fn and src_tag == .Fn) {
2658327268 return try sema.coerceInMemoryAllowedFns(block, dest_ty, src_ty, target, dest_src, src_src);
......@@ -26585,8 +27270,8 @@ fn coerceInMemoryAllowed(
2658527270
2658627271 // Error Unions
2658727272 if (dest_tag == .ErrorUnion and src_tag == .ErrorUnion) {
26588 const dest_payload = dest_ty.errorUnionPayload();
26589 const src_payload = src_ty.errorUnionPayload();
27273 const dest_payload = dest_ty.errorUnionPayload(mod);
27274 const src_payload = src_ty.errorUnionPayload(mod);
2659027275 const child = try sema.coerceInMemoryAllowed(block, dest_payload, src_payload, dest_is_mut, target, dest_src, src_src);
2659127276 if (child != .ok) {
2659227277 return InMemoryCoercionResult{ .error_union_payload = .{
......@@ -26595,7 +27280,7 @@ fn coerceInMemoryAllowed(
2659527280 .wanted = dest_payload,
2659627281 } };
2659727282 }
26598 return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(), src_ty.errorUnionSet(), dest_is_mut, target, dest_src, src_src);
27283 return try sema.coerceInMemoryAllowed(block, dest_ty.errorUnionSet(mod), src_ty.errorUnionSet(mod), dest_is_mut, target, dest_src, src_src);
2659927284 }
2660027285
2660127286 // Error Sets
......@@ -26605,8 +27290,8 @@ fn coerceInMemoryAllowed(
2660527290
2660627291 // Arrays
2660727292 if (dest_tag == .Array and src_tag == .Array) {
26608 const dest_info = dest_ty.arrayInfo();
26609 const src_info = src_ty.arrayInfo();
27293 const dest_info = dest_ty.arrayInfo(mod);
27294 const src_info = src_ty.arrayInfo(mod);
2661027295 if (dest_info.len != src_info.len) {
2661127296 return InMemoryCoercionResult{ .array_len = .{
2661227297 .actual = src_info.len,
......@@ -26624,11 +27309,15 @@ fn coerceInMemoryAllowed(
2662427309 }
2662527310 const ok_sent = dest_info.sentinel == null or
2662627311 (src_info.sentinel != null and
26627 dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.elem_type, sema.mod));
27312 dest_info.sentinel.?.eql(
27313 try mod.getCoerced(src_info.sentinel.?, dest_info.elem_type),
27314 dest_info.elem_type,
27315 mod,
27316 ));
2662827317 if (!ok_sent) {
2662927318 return InMemoryCoercionResult{ .array_sentinel = .{
26630 .actual = src_info.sentinel orelse Value.initTag(.unreachable_value),
26631 .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value),
27319 .actual = src_info.sentinel orelse Value.@"unreachable",
27320 .wanted = dest_info.sentinel orelse Value.@"unreachable",
2663227321 .ty = dest_info.elem_type,
2663327322 } };
2663427323 }
......@@ -26637,8 +27326,8 @@ fn coerceInMemoryAllowed(
2663727326
2663827327 // Vectors
2663927328 if (dest_tag == .Vector and src_tag == .Vector) {
26640 const dest_len = dest_ty.vectorLen();
26641 const src_len = src_ty.vectorLen();
27329 const dest_len = dest_ty.vectorLen(mod);
27330 const src_len = src_ty.vectorLen(mod);
2664227331 if (dest_len != src_len) {
2664327332 return InMemoryCoercionResult{ .vector_len = .{
2664427333 .actual = src_len,
......@@ -26646,8 +27335,8 @@ fn coerceInMemoryAllowed(
2664627335 } };
2664727336 }
2664827337
26649 const dest_elem_ty = dest_ty.scalarType();
26650 const src_elem_ty = src_ty.scalarType();
27338 const dest_elem_ty = dest_ty.scalarType(mod);
27339 const src_elem_ty = src_ty.scalarType(mod);
2665127340 const child = try sema.coerceInMemoryAllowed(block, dest_elem_ty, src_elem_ty, dest_is_mut, target, dest_src, src_src);
2665227341 if (child != .ok) {
2665327342 return InMemoryCoercionResult{ .vector_elem = .{
......@@ -26668,15 +27357,15 @@ fn coerceInMemoryAllowed(
2666827357 .wanted = dest_ty,
2666927358 } };
2667027359 }
26671 const dest_child_type = dest_ty.optionalChild(&dest_buf);
26672 const src_child_type = src_ty.optionalChild(&src_buf);
27360 const dest_child_type = dest_ty.optionalChild(mod);
27361 const src_child_type = src_ty.optionalChild(mod);
2667327362
2667427363 const child = try sema.coerceInMemoryAllowed(block, dest_child_type, src_child_type, dest_is_mut, target, dest_src, src_src);
2667527364 if (child != .ok) {
2667627365 return InMemoryCoercionResult{ .optional_child = .{
2667727366 .child = try child.dupe(sema.arena),
26678 .actual = try src_child_type.copy(sema.arena),
26679 .wanted = try dest_child_type.copy(sema.arena),
27367 .actual = src_child_type,
27368 .wanted = dest_child_type,
2668027369 } };
2668127370 }
2668227371
......@@ -26697,138 +27386,108 @@ fn coerceInMemoryAllowedErrorSets(
2669727386 dest_src: LazySrcLoc,
2669827387 src_src: LazySrcLoc,
2669927388) !InMemoryCoercionResult {
27389 const mod = sema.mod;
27390 const gpa = sema.gpa;
27391 const ip = &mod.intern_pool;
27392
2670027393 // Coercion to `anyerror`. Note that this check can return false negatives
2670127394 // in case the error sets did not get resolved.
26702 if (dest_ty.isAnyError()) {
27395 if (dest_ty.isAnyError(mod)) {
2670327396 return .ok;
2670427397 }
2670527398
26706 if (dest_ty.castTag(.error_set_inferred)) |dst_payload| {
26707 const dst_ies = dst_payload.data;
27399 if (mod.typeToInferredErrorSetIndex(dest_ty).unwrap()) |dst_ies_index| {
27400 const dst_ies = mod.inferredErrorSetPtr(dst_ies_index);
2670827401 // We will make an effort to return `ok` without resolving either error set, to
2670927402 // avoid unnecessary "unable to resolve error set" dependency loop errors.
26710 switch (src_ty.tag()) {
26711 .error_set_inferred => {
26712 // If both are inferred error sets of functions, and
26713 // the dest includes the source function, the coercion is OK.
26714 // This check is important because it works without forcing a full resolution
26715 // of inferred error sets.
26716 const src_ies = src_ty.castTag(.error_set_inferred).?.data;
26717
26718 if (dst_ies.inferred_error_sets.contains(src_ies)) {
26719 return .ok;
26720 }
26721 },
26722 .error_set_single => {
26723 const name = src_ty.castTag(.error_set_single).?.data;
26724 if (dst_ies.errors.contains(name)) return .ok;
26725 },
26726 .error_set_merged => {
26727 const names = src_ty.castTag(.error_set_merged).?.data.keys();
26728 for (names) |name| {
26729 if (!dst_ies.errors.contains(name)) break;
26730 } else return .ok;
26731 },
26732 .error_set => {
26733 const names = src_ty.castTag(.error_set).?.data.names.keys();
26734 for (names) |name| {
26735 if (!dst_ies.errors.contains(name)) break;
26736 } else return .ok;
26737 },
26738 .anyerror => {},
26739 else => unreachable,
27403 switch (src_ty.toIntern()) {
27404 .anyerror_type => {},
27405 else => switch (ip.indexToKey(src_ty.toIntern())) {
27406 .inferred_error_set_type => |src_index| {
27407 // If both are inferred error sets of functions, and
27408 // the dest includes the source function, the coercion is OK.
27409 // This check is important because it works without forcing a full resolution
27410 // of inferred error sets.
27411 if (dst_ies.inferred_error_sets.contains(src_index)) {
27412 return .ok;
27413 }
27414 },
27415 .error_set_type => |error_set_type| {
27416 for (error_set_type.names) |name| {
27417 if (!dst_ies.errors.contains(name)) break;
27418 } else return .ok;
27419 },
27420 else => unreachable,
27421 },
2674027422 }
2674127423
26742 if (dst_ies.func == sema.owner_func) {
27424 if (dst_ies.func == sema.owner_func_index.unwrap()) {
2674327425 // We are trying to coerce an error set to the current function's
2674427426 // inferred error set.
26745 try dst_ies.addErrorSet(sema.gpa, src_ty);
27427 try dst_ies.addErrorSet(src_ty, ip, gpa);
2674627428 return .ok;
2674727429 }
2674827430
26749 try sema.resolveInferredErrorSet(block, dest_src, dst_payload.data);
27431 try sema.resolveInferredErrorSet(block, dest_src, dst_ies_index);
2675027432 // isAnyError might have changed from a false negative to a true positive after resolution.
26751 if (dest_ty.isAnyError()) {
27433 if (dest_ty.isAnyError(mod)) {
2675227434 return .ok;
2675327435 }
2675427436 }
2675527437
26756 var missing_error_buf = std.ArrayList([]const u8).init(sema.gpa);
27438 var missing_error_buf = std.ArrayList(InternPool.NullTerminatedString).init(gpa);
2675727439 defer missing_error_buf.deinit();
2675827440
26759 switch (src_ty.tag()) {
26760 .error_set_inferred => {
26761 const src_data = src_ty.castTag(.error_set_inferred).?.data;
27441 switch (src_ty.toIntern()) {
27442 .anyerror_type => switch (ip.indexToKey(dest_ty.toIntern())) {
27443 .inferred_error_set_type => unreachable, // Caught by dest_ty.isAnyError(mod) above.
27444 .simple_type => unreachable, // filtered out above
27445 .error_set_type => return .from_anyerror,
27446 else => unreachable,
27447 },
27448
27449 else => switch (ip.indexToKey(src_ty.toIntern())) {
27450 .inferred_error_set_type => |src_index| {
27451 const src_data = mod.inferredErrorSetPtr(src_index);
2676227452
26763 try sema.resolveInferredErrorSet(block, src_src, src_data);
26764 // src anyerror status might have changed after the resolution.
26765 if (src_ty.isAnyError()) {
26766 // dest_ty.isAnyError() == true is already checked for at this point.
26767 return .from_anyerror;
26768 }
27453 try sema.resolveInferredErrorSet(block, src_src, src_index);
27454 // src anyerror status might have changed after the resolution.
27455 if (src_ty.isAnyError(mod)) {
27456 // dest_ty.isAnyError(mod) == true is already checked for at this point.
27457 return .from_anyerror;
27458 }
2676927459
26770 for (src_data.errors.keys()) |key| {
26771 if (!dest_ty.errorSetHasField(key)) {
26772 try missing_error_buf.append(key);
27460 for (src_data.errors.keys()) |key| {
27461 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), key)) {
27462 try missing_error_buf.append(key);
27463 }
2677327464 }
26774 }
2677527465
26776 if (missing_error_buf.items.len != 0) {
26777 return InMemoryCoercionResult{
26778 .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
26779 };
26780 }
27466 if (missing_error_buf.items.len != 0) {
27467 return InMemoryCoercionResult{
27468 .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items),
27469 };
27470 }
2678127471
26782 return .ok;
26783 },
26784 .error_set_single => {
26785 const name = src_ty.castTag(.error_set_single).?.data;
26786 if (dest_ty.errorSetHasField(name)) {
2678727472 return .ok;
26788 }
26789 const list = try sema.arena.alloc([]const u8, 1);
26790 list[0] = name;
26791 return InMemoryCoercionResult{ .missing_error = list };
26792 },
26793 .error_set_merged => {
26794 const names = src_ty.castTag(.error_set_merged).?.data.keys();
26795 for (names) |name| {
26796 if (!dest_ty.errorSetHasField(name)) {
26797 try missing_error_buf.append(name);
27473 },
27474 .error_set_type => |error_set_type| {
27475 for (error_set_type.names) |name| {
27476 if (!Type.errorSetHasFieldIp(ip, dest_ty.toIntern(), name)) {
27477 try missing_error_buf.append(name);
27478 }
2679827479 }
26799 }
26800
26801 if (missing_error_buf.items.len != 0) {
26802 return InMemoryCoercionResult{
26803 .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
26804 };
26805 }
2680627480
26807 return .ok;
26808 },
26809 .error_set => {
26810 const names = src_ty.castTag(.error_set).?.data.names.keys();
26811 for (names) |name| {
26812 if (!dest_ty.errorSetHasField(name)) {
26813 try missing_error_buf.append(name);
27481 if (missing_error_buf.items.len != 0) {
27482 return InMemoryCoercionResult{
27483 .missing_error = try sema.arena.dupe(InternPool.NullTerminatedString, missing_error_buf.items),
27484 };
2681427485 }
26815 }
2681627486
26817 if (missing_error_buf.items.len != 0) {
26818 return InMemoryCoercionResult{
26819 .missing_error = try sema.arena.dupe([]const u8, missing_error_buf.items),
26820 };
26821 }
26822
26823 return .ok;
26824 },
26825 .anyerror => switch (dest_ty.tag()) {
26826 .error_set_inferred => unreachable, // Caught by dest_ty.isAnyError() above.
26827 .error_set_single, .error_set_merged, .error_set => return .from_anyerror,
26828 .anyerror => unreachable, // Filtered out above.
27487 return .ok;
27488 },
2682927489 else => unreachable,
2683027490 },
26831 else => unreachable,
2683227491 }
2683327492
2683427493 unreachable;
......@@ -26843,69 +27502,95 @@ fn coerceInMemoryAllowedFns(
2684327502 dest_src: LazySrcLoc,
2684427503 src_src: LazySrcLoc,
2684527504) !InMemoryCoercionResult {
26846 const dest_info = dest_ty.fnInfo();
26847 const src_info = src_ty.fnInfo();
27505 const mod = sema.mod;
2684827506
26849 if (dest_info.is_var_args != src_info.is_var_args) {
26850 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
26851 }
27507 {
27508 const dest_info = mod.typeToFunc(dest_ty).?;
27509 const src_info = mod.typeToFunc(src_ty).?;
2685227510
26853 if (dest_info.is_generic != src_info.is_generic) {
26854 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
26855 }
27511 if (dest_info.is_var_args != src_info.is_var_args) {
27512 return InMemoryCoercionResult{ .fn_var_args = dest_info.is_var_args };
27513 }
2685627514
26857 if (dest_info.cc != src_info.cc) {
26858 return InMemoryCoercionResult{ .fn_cc = .{
26859 .actual = src_info.cc,
26860 .wanted = dest_info.cc,
26861 } };
26862 }
27515 if (dest_info.is_generic != src_info.is_generic) {
27516 return InMemoryCoercionResult{ .fn_generic = dest_info.is_generic };
27517 }
2686327518
26864 if (!src_info.return_type.isNoReturn()) {
26865 const rt = try sema.coerceInMemoryAllowed(block, dest_info.return_type, src_info.return_type, false, target, dest_src, src_src);
26866 if (rt != .ok) {
26867 return InMemoryCoercionResult{ .fn_return_type = .{
26868 .child = try rt.dupe(sema.arena),
26869 .actual = src_info.return_type,
26870 .wanted = dest_info.return_type,
27519 if (dest_info.cc != src_info.cc) {
27520 return InMemoryCoercionResult{ .fn_cc = .{
27521 .actual = src_info.cc,
27522 .wanted = dest_info.cc,
2687127523 } };
2687227524 }
26873 }
2687427525
26875 if (dest_info.param_types.len != src_info.param_types.len) {
26876 return InMemoryCoercionResult{ .fn_param_count = .{
26877 .actual = src_info.param_types.len,
26878 .wanted = dest_info.param_types.len,
26879 } };
27526 switch (src_info.return_type) {
27527 .noreturn_type, .generic_poison_type => {},
27528 else => {
27529 const dest_return_type = dest_info.return_type.toType();
27530 const src_return_type = src_info.return_type.toType();
27531 const rt = try sema.coerceInMemoryAllowed(block, dest_return_type, src_return_type, false, target, dest_src, src_src);
27532 if (rt != .ok) {
27533 return InMemoryCoercionResult{ .fn_return_type = .{
27534 .child = try rt.dupe(sema.arena),
27535 .actual = src_return_type,
27536 .wanted = dest_return_type,
27537 } };
27538 }
27539 },
27540 }
2688027541 }
2688127542
26882 if (dest_info.noalias_bits != src_info.noalias_bits) {
26883 return InMemoryCoercionResult{ .fn_param_noalias = .{
26884 .actual = src_info.noalias_bits,
26885 .wanted = dest_info.noalias_bits,
26886 } };
26887 }
27543 const params_len = params_len: {
27544 const dest_info = mod.typeToFunc(dest_ty).?;
27545 const src_info = mod.typeToFunc(src_ty).?;
2688827546
26889 for (dest_info.param_types, 0..) |dest_param_ty, i| {
26890 const src_param_ty = src_info.param_types[i];
27547 if (dest_info.param_types.len != src_info.param_types.len) {
27548 return InMemoryCoercionResult{ .fn_param_count = .{
27549 .actual = src_info.param_types.len,
27550 .wanted = dest_info.param_types.len,
27551 } };
27552 }
2689127553
26892 if (dest_info.comptime_params[i] != src_info.comptime_params[i]) {
26893 return InMemoryCoercionResult{ .fn_param_comptime = .{
26894 .index = i,
26895 .wanted = dest_info.comptime_params[i],
27554 if (dest_info.noalias_bits != src_info.noalias_bits) {
27555 return InMemoryCoercionResult{ .fn_param_noalias = .{
27556 .actual = src_info.noalias_bits,
27557 .wanted = dest_info.noalias_bits,
2689627558 } };
2689727559 }
2689827560
26899 // Note: Cast direction is reversed here.
26900 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);
26901 if (param != .ok) {
26902 return InMemoryCoercionResult{ .fn_param = .{
26903 .child = try param.dupe(sema.arena),
26904 .actual = src_param_ty,
26905 .wanted = dest_param_ty,
26906 .index = i,
27561 break :params_len dest_info.param_types.len;
27562 };
27563
27564 for (0..params_len) |param_i| {
27565 const dest_info = mod.typeToFunc(dest_ty).?;
27566 const src_info = mod.typeToFunc(src_ty).?;
27567
27568 const dest_param_ty = dest_info.param_types[param_i].toType();
27569 const src_param_ty = src_info.param_types[param_i].toType();
27570
27571 const param_i_small = @intCast(u5, param_i);
27572 if (dest_info.paramIsComptime(param_i_small) != src_info.paramIsComptime(param_i_small)) {
27573 return InMemoryCoercionResult{ .fn_param_comptime = .{
27574 .index = param_i,
27575 .wanted = dest_info.paramIsComptime(param_i_small),
2690727576 } };
2690827577 }
27578
27579 switch (src_param_ty.toIntern()) {
27580 .generic_poison_type => {},
27581 else => {
27582 // Note: Cast direction is reversed here.
27583 const param = try sema.coerceInMemoryAllowed(block, src_param_ty, dest_param_ty, false, target, dest_src, src_src);
27584 if (param != .ok) {
27585 return InMemoryCoercionResult{ .fn_param = .{
27586 .child = try param.dupe(sema.arena),
27587 .actual = src_param_ty,
27588 .wanted = dest_param_ty,
27589 .index = param_i,
27590 } };
27591 }
27592 },
27593 }
2690927594 }
2691027595
2691127596 return .ok;
......@@ -26923,8 +27608,9 @@ fn coerceInMemoryAllowedPtrs(
2692327608 dest_src: LazySrcLoc,
2692427609 src_src: LazySrcLoc,
2692527610) !InMemoryCoercionResult {
26926 const dest_info = dest_ptr_ty.ptrInfo().data;
26927 const src_info = src_ptr_ty.ptrInfo().data;
27611 const mod = sema.mod;
27612 const dest_info = dest_ptr_ty.ptrInfo(mod);
27613 const src_info = src_ptr_ty.ptrInfo(mod);
2692827614
2692927615 const ok_ptr_size = src_info.size == dest_info.size or
2693027616 src_info.size == .C or dest_info.size == .C;
......@@ -26964,8 +27650,8 @@ fn coerceInMemoryAllowedPtrs(
2696427650 } };
2696527651 }
2696627652
26967 const dest_allow_zero = dest_ty.ptrAllowsZero();
26968 const src_allow_zero = src_ty.ptrAllowsZero();
27653 const dest_allow_zero = dest_ty.ptrAllowsZero(mod);
27654 const src_allow_zero = src_ty.ptrAllowsZero(mod);
2696927655
2697027656 const ok_allows_zero = (dest_allow_zero and
2697127657 (src_allow_zero or !dest_is_mut)) or
......@@ -26989,12 +27675,15 @@ fn coerceInMemoryAllowedPtrs(
2698927675 }
2699027676
2699127677 const ok_sent = dest_info.sentinel == null or src_info.size == .C or
26992 (src_info.sentinel != null and
26993 dest_info.sentinel.?.eql(src_info.sentinel.?, dest_info.pointee_type, sema.mod));
27678 (src_info.sentinel != null and dest_info.sentinel.?.eql(
27679 try mod.getCoerced(src_info.sentinel.?, dest_info.pointee_type),
27680 dest_info.pointee_type,
27681 sema.mod,
27682 ));
2699427683 if (!ok_sent) {
2699527684 return InMemoryCoercionResult{ .ptr_sentinel = .{
26996 .actual = src_info.sentinel orelse Value.initTag(.unreachable_value),
26997 .wanted = dest_info.sentinel orelse Value.initTag(.unreachable_value),
27685 .actual = src_info.sentinel orelse Value.@"unreachable",
27686 .wanted = dest_info.sentinel orelse Value.@"unreachable",
2699827687 .ty = dest_info.pointee_type,
2699927688 } };
2700027689 }
......@@ -27013,12 +27702,12 @@ fn coerceInMemoryAllowedPtrs(
2701327702 const src_align = if (src_info.@"align" != 0)
2701427703 src_info.@"align"
2701527704 else
27016 src_info.pointee_type.abiAlignment(target);
27705 src_info.pointee_type.abiAlignment(mod);
2701727706
2701827707 const dest_align = if (dest_info.@"align" != 0)
2701927708 dest_info.@"align"
2702027709 else
27021 dest_info.pointee_type.abiAlignment(target);
27710 dest_info.pointee_type.abiAlignment(mod);
2702227711
2702327712 if (dest_align > src_align) {
2702427713 return InMemoryCoercionResult{ .ptr_alignment = .{
......@@ -27041,8 +27730,9 @@ fn coerceVarArgParam(
2704127730) !Air.Inst.Ref {
2704227731 if (block.is_typeof) return inst;
2704327732
27733 const mod = sema.mod;
2704427734 const uncasted_ty = sema.typeOf(inst);
27045 const coerced = switch (uncasted_ty.zigTypeTag()) {
27735 const coerced = switch (uncasted_ty.zigTypeTag(mod)) {
2704627736 // TODO consider casting to c_int/f64 if they fit
2704727737 .ComptimeInt, .ComptimeFloat => return sema.fail(
2704827738 block,
......@@ -27052,7 +27742,7 @@ fn coerceVarArgParam(
2705227742 ),
2705327743 .Fn => blk: {
2705427744 const fn_val = try sema.resolveConstValue(block, .unneeded, inst, "");
27055 const fn_decl = fn_val.pointerDecl().?;
27745 const fn_decl = fn_val.pointerDecl(mod).?;
2705627746 break :blk try sema.analyzeDeclRef(fn_decl);
2705727747 },
2705827748 .Array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}),
......@@ -27077,7 +27767,7 @@ fn coerceVarArgParam(
2707727767 errdefer msg.destroy(sema.gpa);
2707827768
2707927769 const src_decl = sema.mod.declPtr(block.src_decl);
27080 try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl), coerced_ty, .param_ty);
27770 try sema.explainWhyTypeIsNotExtern(msg, inst_src.toSrcLoc(src_decl, mod), coerced_ty, .param_ty);
2708127771
2708227772 try sema.addDeclaredHereNote(msg, coerced_ty);
2708327773 break :msg msg;
......@@ -27109,11 +27799,12 @@ fn storePtr2(
2710927799 operand_src: LazySrcLoc,
2711027800 air_tag: Air.Inst.Tag,
2711127801) CompileError!void {
27802 const mod = sema.mod;
2711227803 const ptr_ty = sema.typeOf(ptr);
27113 if (ptr_ty.isConstPtr())
27804 if (ptr_ty.isConstPtr(mod))
2711427805 return sema.fail(block, ptr_src, "cannot assign to constant", .{});
2711527806
27116 const elem_ty = ptr_ty.childType();
27807 const elem_ty = ptr_ty.childType(mod);
2711727808
2711827809 // To generate better code for tuples, we detect a tuple operand here, and
2711927810 // analyze field loads and stores directly. This avoids an extra allocation + memcpy
......@@ -27124,8 +27815,8 @@ fn storePtr2(
2712427815 // this code does not handle tuple-to-struct coercion which requires dealing with missing
2712527816 // fields.
2712627817 const operand_ty = sema.typeOf(uncasted_operand);
27127 if (operand_ty.isTuple() and elem_ty.zigTypeTag() == .Array) {
27128 const field_count = operand_ty.structFieldCount();
27818 if (operand_ty.isTuple(mod) and elem_ty.zigTypeTag(mod) == .Array) {
27819 const field_count = operand_ty.structFieldCount(mod);
2712927820 var i: u32 = 0;
2713027821 while (i < field_count) : (i += 1) {
2713127822 const elem_src = operand_src; // TODO better source location
......@@ -27149,7 +27840,7 @@ fn storePtr2(
2714927840 // as well as working around an LLVM bug:
2715027841 // https://github.com/ziglang/zig/issues/11154
2715127842 if (sema.obtainBitCastedVectorPtr(ptr)) |vector_ptr| {
27152 const vector_ty = sema.typeOf(vector_ptr).childType();
27843 const vector_ty = sema.typeOf(vector_ptr).childType(mod);
2715327844 const vector = sema.coerceExtra(block, vector_ty, uncasted_operand, operand_src, .{ .is_ret = is_ret }) catch |err| switch (err) {
2715427845 error.NotCoercible => unreachable,
2715527846 else => |e| return e,
......@@ -27169,7 +27860,7 @@ fn storePtr2(
2716927860 try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src);
2717027861 break :rs operand_src;
2717127862 };
27172 if (ptr_val.isComptimeMutablePtr()) {
27863 if (ptr_val.isComptimeMutablePtr(mod)) {
2717327864 try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty);
2717427865 return;
2717527866 } else break :rs ptr_src;
......@@ -27190,7 +27881,7 @@ fn storePtr2(
2719027881 try sema.requireRuntimeBlock(block, src, runtime_src);
2719127882 try sema.queueFullTypeResolution(elem_ty);
2719227883
27193 if (ptr_ty.ptrInfo().data.vector_index == .runtime) {
27884 if (ptr_ty.ptrInfo(mod).vector_index == .runtime) {
2719427885 const ptr_inst = Air.refToIndex(ptr).?;
2719527886 const air_tags = sema.air_instructions.items(.tag);
2719627887 if (air_tags[ptr_inst] == .ptr_elem_ptr) {
......@@ -27224,30 +27915,27 @@ fn storePtr2(
2722427915/// pointer. Only if the final element type matches the vector element type, and the
2722527916/// lengths match.
2722627917fn obtainBitCastedVectorPtr(sema: *Sema, ptr: Air.Inst.Ref) ?Air.Inst.Ref {
27227 const array_ty = sema.typeOf(ptr).childType();
27228 if (array_ty.zigTypeTag() != .Array) return null;
27229 var ptr_inst = Air.refToIndex(ptr) orelse return null;
27918 const mod = sema.mod;
27919 const array_ty = sema.typeOf(ptr).childType(mod);
27920 if (array_ty.zigTypeTag(mod) != .Array) return null;
27921 var ptr_ref = ptr;
27922 var ptr_inst = Air.refToIndex(ptr_ref) orelse return null;
2723027923 const air_datas = sema.air_instructions.items(.data);
2723127924 const air_tags = sema.air_instructions.items(.tag);
27232 const prev_ptr = while (air_tags[ptr_inst] == .bitcast) {
27233 const prev_ptr = air_datas[ptr_inst].ty_op.operand;
27234 const prev_ptr_ty = sema.typeOf(prev_ptr);
27235 const prev_ptr_child_ty = switch (prev_ptr_ty.tag()) {
27236 .single_mut_pointer => prev_ptr_ty.castTag(.single_mut_pointer).?.data,
27237 .pointer => prev_ptr_ty.castTag(.pointer).?.data.pointee_type,
27238 else => return null,
27239 };
27240 if (prev_ptr_child_ty.zigTypeTag() == .Vector) break prev_ptr;
27241 ptr_inst = Air.refToIndex(prev_ptr) orelse return null;
27925 const vector_ty = while (air_tags[ptr_inst] == .bitcast) {
27926 ptr_ref = air_datas[ptr_inst].ty_op.operand;
27927 if (!sema.isKnownZigType(ptr_ref, .Pointer)) return null;
27928 const child_ty = sema.typeOf(ptr_ref).childType(mod);
27929 if (child_ty.zigTypeTag(mod) == .Vector) break child_ty;
27930 ptr_inst = Air.refToIndex(ptr_ref) orelse return null;
2724227931 } else return null;
2724327932
2724427933 // We have a pointer-to-array and a pointer-to-vector. If the elements and
2724527934 // lengths match, return the result.
27246 const vector_ty = sema.typeOf(prev_ptr).childType();
27247 if (array_ty.childType().eql(vector_ty.childType(), sema.mod) and
27248 array_ty.arrayLen() == vector_ty.vectorLen())
27935 if (array_ty.childType(mod).eql(vector_ty.childType(mod), sema.mod) and
27936 array_ty.arrayLen(mod) == vector_ty.vectorLen(mod))
2724927937 {
27250 return prev_ptr;
27938 return ptr_ref;
2725127939 } else {
2725227940 return null;
2725327941 }
......@@ -27263,54 +27951,55 @@ fn storePtrVal(
2726327951 operand_val: Value,
2726427952 operand_ty: Type,
2726527953) !void {
27954 const mod = sema.mod;
2726627955 var mut_kit = try sema.beginComptimePtrMutation(block, src, ptr_val, operand_ty);
27267 try sema.checkComptimeVarStore(block, src, mut_kit.decl_ref_mut);
27956 try sema.checkComptimeVarStore(block, src, mut_kit.mut_decl);
2726827957
2726927958 switch (mut_kit.pointee) {
2727027959 .direct => |val_ptr| {
27271 if (mut_kit.decl_ref_mut.runtime_index == .comptime_field_ptr) {
27272 if (!operand_val.eql(val_ptr.*, operand_ty, sema.mod)) {
27960 if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) {
27961 if (!operand_val.eql(val_ptr.*, operand_ty, mod)) {
2727327962 // TODO use failWithInvalidComptimeFieldStore
2727427963 return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{});
2727527964 }
2727627965 return;
2727727966 }
27278 const arena = mut_kit.beginArena(sema.mod);
27279 defer mut_kit.finishArena(sema.mod);
27280
27281 val_ptr.* = try operand_val.copy(arena);
27967 val_ptr.* = (try operand_val.intern(operand_ty, mod)).toValue();
2728227968 },
2728327969 .reinterpret => |reinterpret| {
27284 const target = sema.mod.getTarget();
27285 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(target));
27970 const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod));
2728627971 const buffer = try sema.gpa.alloc(u8, abi_size);
2728727972 defer sema.gpa.free(buffer);
27288 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, sema.mod, buffer) catch |err| switch (err) {
27973 reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) {
27974 error.OutOfMemory => return error.OutOfMemory,
2728927975 error.ReinterpretDeclRef => unreachable,
2729027976 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
27291 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(sema.mod)}),
27977 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(mod)}),
2729227978 };
27293 operand_val.writeToMemory(operand_ty, sema.mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) {
27979 operand_val.writeToMemory(operand_ty, mod, buffer[reinterpret.byte_offset..]) catch |err| switch (err) {
27980 error.OutOfMemory => return error.OutOfMemory,
2729427981 error.ReinterpretDeclRef => unreachable,
2729527982 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
27296 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(sema.mod)}),
27983 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{mut_kit.ty.fmt(mod)}),
2729727984 };
2729827985
27299 const arena = mut_kit.beginArena(sema.mod);
27300 defer mut_kit.finishArena(sema.mod);
27301
27302 reinterpret.val_ptr.* = try Value.readFromMemory(mut_kit.ty, sema.mod, buffer, arena);
27986 reinterpret.val_ptr.* = (try (try Value.readFromMemory(mut_kit.ty, mod, buffer, sema.arena)).intern(mut_kit.ty, mod)).toValue();
2730327987 },
2730427988 .bad_decl_ty, .bad_ptr_ty => {
2730527989 // TODO show the decl declaration site in a note and explain whether the decl
2730627990 // or the pointer is the problematic type
27307 return sema.fail(block, src, "comptime mutation of a reinterpreted pointer requires type '{}' to have a well-defined memory layout", .{mut_kit.ty.fmt(sema.mod)});
27991 return sema.fail(
27992 block,
27993 src,
27994 "comptime mutation of a reinterpreted pointer requires type '{}' to have a well-defined memory layout",
27995 .{mut_kit.ty.fmt(mod)},
27996 );
2730827997 },
2730927998 }
2731027999}
2731128000
2731228001const ComptimePtrMutationKit = struct {
27313 decl_ref_mut: Value.Payload.DeclRefMut.Data,
28002 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,
2731428003 pointee: union(enum) {
2731528004 /// The pointer type matches the actual comptime Value so a direct
2731628005 /// modification is possible.
......@@ -27333,18 +28022,6 @@ const ComptimePtrMutationKit = struct {
2733328022 bad_ptr_ty,
2733428023 },
2733528024 ty: Type,
27336 decl_arena: std.heap.ArenaAllocator = undefined,
27337
27338 fn beginArena(self: *ComptimePtrMutationKit, mod: *Module) Allocator {
27339 const decl = mod.declPtr(self.decl_ref_mut.decl_index);
27340 return decl.value_arena.?.acquire(mod.gpa, &self.decl_arena);
27341 }
27342
27343 fn finishArena(self: *ComptimePtrMutationKit, mod: *Module) void {
27344 const decl = mod.declPtr(self.decl_ref_mut.decl_index);
27345 decl.value_arena.?.release(&self.decl_arena);
27346 self.decl_arena = undefined;
27347 }
2734828025};
2734928026
2735028027fn beginComptimePtrMutation(
......@@ -27354,201 +28031,251 @@ fn beginComptimePtrMutation(
2735428031 ptr_val: Value,
2735528032 ptr_elem_ty: Type,
2735628033) CompileError!ComptimePtrMutationKit {
27357 const target = sema.mod.getTarget();
27358 switch (ptr_val.tag()) {
27359 .decl_ref_mut => {
27360 const decl_ref_mut = ptr_val.castTag(.decl_ref_mut).?.data;
27361 const decl = sema.mod.declPtr(decl_ref_mut.decl_index);
27362 return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, decl_ref_mut);
27363 },
27364 .comptime_field_ptr => {
27365 const payload = ptr_val.castTag(.comptime_field_ptr).?.data;
28034 const mod = sema.mod;
28035 const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr;
28036 switch (ptr.addr) {
28037 .decl, .int => unreachable, // isComptimeMutablePtr has been checked already
28038 .mut_decl => |mut_decl| {
28039 const decl = mod.declPtr(mut_decl.decl);
28040 return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl);
28041 },
28042 .comptime_field => |comptime_field| {
2736628043 const duped = try sema.arena.create(Value);
27367 duped.* = payload.field_val;
27368 return sema.beginComptimePtrMutationInner(block, src, payload.field_ty, duped, ptr_elem_ty, .{
27369 .decl_index = @intToEnum(Module.Decl.Index, 0),
28044 duped.* = comptime_field.toValue();
28045 return sema.beginComptimePtrMutationInner(block, src, mod.intern_pool.typeOf(comptime_field).toType(), duped, ptr_elem_ty, .{
28046 .decl = undefined,
2737028047 .runtime_index = .comptime_field_ptr,
2737128048 });
2737228049 },
27373 .elem_ptr => {
27374 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
27375 var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.array_ptr, elem_ptr.elem_ty);
28050 .eu_payload => |eu_ptr| {
28051 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);
28052 var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.toValue(), eu_ty);
28053 switch (parent.pointee) {
28054 .direct => |val_ptr| {
28055 const payload_ty = parent.ty.errorUnionPayload(mod);
28056 if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) {
28057 return ComptimePtrMutationKit{
28058 .mut_decl = parent.mut_decl,
28059 .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data },
28060 .ty = payload_ty,
28061 };
28062 } else {
28063 // An error union has been initialized to undefined at comptime and now we
28064 // are for the first time setting the payload. We must change the
28065 // representation of the error union from `undef` to `opt_payload`.
28066
28067 const payload = try sema.arena.create(Value.Payload.SubValue);
28068 payload.* = .{
28069 .base = .{ .tag = .eu_payload },
28070 .data = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
28071 };
28072
28073 val_ptr.* = Value.initPayload(&payload.base);
28074
28075 return ComptimePtrMutationKit{
28076 .mut_decl = parent.mut_decl,
28077 .pointee = .{ .direct = &payload.data },
28078 .ty = payload_ty,
28079 };
28080 }
28081 },
28082 .bad_decl_ty, .bad_ptr_ty => return parent,
28083 // Even though the parent value type has well-defined memory layout, our
28084 // pointer type does not.
28085 .reinterpret => return ComptimePtrMutationKit{
28086 .mut_decl = parent.mut_decl,
28087 .pointee = .bad_ptr_ty,
28088 .ty = eu_ty,
28089 },
28090 }
28091 },
28092 .opt_payload => |opt_ptr| {
28093 const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod);
28094 var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.toValue(), opt_ty);
28095 switch (parent.pointee) {
28096 .direct => |val_ptr| {
28097 const payload_ty = parent.ty.optionalChild(mod);
28098 switch (val_ptr.ip_index) {
28099 .none => return ComptimePtrMutationKit{
28100 .mut_decl = parent.mut_decl,
28101 .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },
28102 .ty = payload_ty,
28103 },
28104 else => {
28105 const payload_val = switch (mod.intern_pool.indexToKey(val_ptr.ip_index)) {
28106 .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }),
28107 .opt => |opt| switch (opt.val) {
28108 .none => try mod.intern(.{ .undef = payload_ty.toIntern() }),
28109 else => |payload| payload,
28110 },
28111 else => unreachable,
28112 };
28113
28114 // An optional has been initialized to undefined at comptime and now we
28115 // are for the first time setting the payload. We must change the
28116 // representation of the optional from `undef` to `opt_payload`.
28117
28118 const payload = try sema.arena.create(Value.Payload.SubValue);
28119 payload.* = .{
28120 .base = .{ .tag = .opt_payload },
28121 .data = payload_val.toValue(),
28122 };
28123
28124 val_ptr.* = Value.initPayload(&payload.base);
28125
28126 return ComptimePtrMutationKit{
28127 .mut_decl = parent.mut_decl,
28128 .pointee = .{ .direct = &payload.data },
28129 .ty = payload_ty,
28130 };
28131 },
28132 }
28133 },
28134 .bad_decl_ty, .bad_ptr_ty => return parent,
28135 // Even though the parent value type has well-defined memory layout, our
28136 // pointer type does not.
28137 .reinterpret => return ComptimePtrMutationKit{
28138 .mut_decl = parent.mut_decl,
28139 .pointee = .bad_ptr_ty,
28140 .ty = opt_ty,
28141 },
28142 }
28143 },
28144 .elem => |elem_ptr| {
28145 const base_elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);
28146 var parent = try sema.beginComptimePtrMutation(block, src, elem_ptr.base.toValue(), base_elem_ty);
2737628147
2737728148 switch (parent.pointee) {
27378 .direct => |val_ptr| switch (parent.ty.zigTypeTag()) {
28149 .direct => |val_ptr| switch (parent.ty.zigTypeTag(mod)) {
2737928150 .Array, .Vector => {
27380 const check_len = parent.ty.arrayLenIncludingSentinel();
28151 const check_len = parent.ty.arrayLenIncludingSentinel(mod);
2738128152 if (elem_ptr.index >= check_len) {
2738228153 // TODO have the parent include the decl so we can say "declared here"
2738328154 return sema.fail(block, src, "comptime store of index {d} out of bounds of array length {d}", .{
2738428155 elem_ptr.index, check_len,
2738528156 });
2738628157 }
27387 const elem_ty = parent.ty.childType();
28158 const elem_ty = parent.ty.childType(mod);
2738828159
2738928160 // We might have a pointer to multiple elements of the array (e.g. a pointer
2739028161 // to a sub-array). In this case, we just have to reinterpret the relevant
2739128162 // bytes of the whole array rather than any single element.
27392 const elem_abi_size_u64 = try sema.typeAbiSize(elem_ptr.elem_ty);
28163 const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty);
2739328164 if (elem_abi_size_u64 < try sema.typeAbiSize(ptr_elem_ty)) {
2739428165 const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64);
28166 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);
2739528167 return .{
27396 .decl_ref_mut = parent.decl_ref_mut,
28168 .mut_decl = parent.mut_decl,
2739728169 .pointee = .{ .reinterpret = .{
2739828170 .val_ptr = val_ptr,
27399 .byte_offset = elem_abi_size * elem_ptr.index,
28171 .byte_offset = elem_abi_size * elem_idx,
2740028172 } },
2740128173 .ty = parent.ty,
2740228174 };
2740328175 }
2740428176
27405 switch (val_ptr.tag()) {
27406 .undef => {
27407 // An array has been initialized to undefined at comptime and now we
27408 // are for the first time setting an element. We must change the representation
27409 // of the array from `undef` to `array`.
27410 const arena = parent.beginArena(sema.mod);
27411 defer parent.finishArena(sema.mod);
28177 switch (val_ptr.ip_index) {
28178 .none => switch (val_ptr.tag()) {
28179 .bytes => {
28180 // An array is memory-optimized to store a slice of bytes, but we are about
28181 // to modify an individual field and the representation has to change.
28182 // If we wanted to avoid this, there would need to be special detection
28183 // elsewhere to identify when writing a value to an array element that is stored
28184 // using the `bytes` tag, and handle it without making a call to this function.
28185 const arena = sema.arena;
28186
28187 const bytes = val_ptr.castTag(.bytes).?.data;
28188 const dest_len = parent.ty.arrayLenIncludingSentinel(mod);
28189 // bytes.len may be one greater than dest_len because of the case when
28190 // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted.
28191 assert(bytes.len >= dest_len);
28192 const elems = try arena.alloc(Value, @intCast(usize, dest_len));
28193 for (elems, 0..) |*elem, i| {
28194 elem.* = try mod.intValue(elem_ty, bytes[i]);
28195 }
2741228196
27413 const array_len_including_sentinel =
27414 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel());
27415 const elems = try arena.alloc(Value, array_len_including_sentinel);
27416 @memset(elems, Value.undef);
28197 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
2741728198
27418 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
28199 return beginComptimePtrMutationInner(
28200 sema,
28201 block,
28202 src,
28203 elem_ty,
28204 &elems[@intCast(usize, elem_ptr.index)],
28205 ptr_elem_ty,
28206 parent.mut_decl,
28207 );
28208 },
28209 .repeated => {
28210 // An array is memory-optimized to store only a single element value, and
28211 // that value is understood to be the same for the entire length of the array.
28212 // However, now we want to modify an individual field and so the
28213 // representation has to change. If we wanted to avoid this, there would
28214 // need to be special detection elsewhere to identify when writing a value to an
28215 // array element that is stored using the `repeated` tag, and handle it
28216 // without making a call to this function.
28217 const arena = sema.arena;
28218
28219 const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena);
28220 const array_len_including_sentinel =
28221 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod));
28222 const elems = try arena.alloc(Value, array_len_including_sentinel);
28223 if (elems.len > 0) elems[0] = repeated_val;
28224 for (elems[1..]) |*elem| {
28225 elem.* = try repeated_val.copy(arena);
28226 }
2741928227
27420 return beginComptimePtrMutationInner(
27421 sema,
27422 block,
27423 src,
27424 elem_ty,
27425 &elems[elem_ptr.index],
27426 ptr_elem_ty,
27427 parent.decl_ref_mut,
27428 );
27429 },
27430 .bytes => {
27431 // An array is memory-optimized to store a slice of bytes, but we are about
27432 // to modify an individual field and the representation has to change.
27433 // If we wanted to avoid this, there would need to be special detection
27434 // elsewhere to identify when writing a value to an array element that is stored
27435 // using the `bytes` tag, and handle it without making a call to this function.
27436 const arena = parent.beginArena(sema.mod);
27437 defer parent.finishArena(sema.mod);
27438
27439 const bytes = val_ptr.castTag(.bytes).?.data;
27440 const dest_len = parent.ty.arrayLenIncludingSentinel();
27441 // bytes.len may be one greater than dest_len because of the case when
27442 // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted.
27443 assert(bytes.len >= dest_len);
27444 const elems = try arena.alloc(Value, @intCast(usize, dest_len));
27445 for (elems, 0..) |*elem, i| {
27446 elem.* = try Value.Tag.int_u64.create(arena, bytes[i]);
27447 }
28228 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
2744828229
27449 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
28230 return beginComptimePtrMutationInner(
28231 sema,
28232 block,
28233 src,
28234 elem_ty,
28235 &elems[@intCast(usize, elem_ptr.index)],
28236 ptr_elem_ty,
28237 parent.mut_decl,
28238 );
28239 },
2745028240
27451 return beginComptimePtrMutationInner(
28241 .aggregate => return beginComptimePtrMutationInner(
2745228242 sema,
2745328243 block,
2745428244 src,
2745528245 elem_ty,
27456 &elems[elem_ptr.index],
28246 &val_ptr.castTag(.aggregate).?.data[@intCast(usize, elem_ptr.index)],
2745728247 ptr_elem_ty,
27458 parent.decl_ref_mut,
27459 );
27460 },
27461 .str_lit => {
27462 // An array is memory-optimized to store a slice of bytes, but we are about
27463 // to modify an individual field and the representation has to change.
27464 // If we wanted to avoid this, there would need to be special detection
27465 // elsewhere to identify when writing a value to an array element that is stored
27466 // using the `str_lit` tag, and handle it without making a call to this function.
27467 const arena = parent.beginArena(sema.mod);
27468 defer parent.finishArena(sema.mod);
27469
27470 const str_lit = val_ptr.castTag(.str_lit).?.data;
27471 const dest_len = parent.ty.arrayLenIncludingSentinel();
27472 const bytes = sema.mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
27473 const elems = try arena.alloc(Value, @intCast(usize, dest_len));
27474 for (bytes, 0..) |byte, i| {
27475 elems[i] = try Value.Tag.int_u64.create(arena, byte);
27476 }
27477 if (parent.ty.sentinel()) |sent_val| {
27478 assert(elems.len == bytes.len + 1);
27479 elems[bytes.len] = sent_val;
27480 }
27481
27482 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
28248 parent.mut_decl,
28249 ),
2748328250
27484 return beginComptimePtrMutationInner(
27485 sema,
27486 block,
27487 src,
27488 elem_ty,
27489 &elems[elem_ptr.index],
27490 ptr_elem_ty,
27491 parent.decl_ref_mut,
27492 );
28251 else => unreachable,
2749328252 },
27494 .repeated => {
27495 // An array is memory-optimized to store only a single element value, and
27496 // that value is understood to be the same for the entire length of the array.
27497 // However, now we want to modify an individual field and so the
27498 // representation has to change. If we wanted to avoid this, there would
27499 // need to be special detection elsewhere to identify when writing a value to an
27500 // array element that is stored using the `repeated` tag, and handle it
27501 // without making a call to this function.
27502 const arena = parent.beginArena(sema.mod);
27503 defer parent.finishArena(sema.mod);
27504
27505 const repeated_val = try val_ptr.castTag(.repeated).?.data.copy(arena);
27506 const array_len_including_sentinel =
27507 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel());
27508 const elems = try arena.alloc(Value, array_len_including_sentinel);
27509 if (elems.len > 0) elems[0] = repeated_val;
27510 for (elems[1..]) |*elem| {
27511 elem.* = try repeated_val.copy(arena);
27512 }
28253 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
28254 .undef => {
28255 // An array has been initialized to undefined at comptime and now we
28256 // are for the first time setting an element. We must change the representation
28257 // of the array from `undef` to `array`.
28258 const arena = sema.arena;
2751328259
27514 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
28260 const array_len_including_sentinel =
28261 try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod));
28262 const elems = try arena.alloc(Value, array_len_including_sentinel);
28263 @memset(elems, (try mod.intern(.{ .undef = elem_ty.toIntern() })).toValue());
2751528264
27516 return beginComptimePtrMutationInner(
27517 sema,
27518 block,
27519 src,
27520 elem_ty,
27521 &elems[elem_ptr.index],
27522 ptr_elem_ty,
27523 parent.decl_ref_mut,
27524 );
27525 },
28265 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
2752628266
27527 .aggregate => return beginComptimePtrMutationInner(
27528 sema,
27529 block,
27530 src,
27531 elem_ty,
27532 &val_ptr.castTag(.aggregate).?.data[elem_ptr.index],
27533 ptr_elem_ty,
27534 parent.decl_ref_mut,
27535 ),
27536
27537 .the_only_possible_value => {
27538 const duped = try sema.arena.create(Value);
27539 duped.* = Value.initTag(.the_only_possible_value);
27540 return beginComptimePtrMutationInner(
27541 sema,
27542 block,
27543 src,
27544 elem_ty,
27545 duped,
27546 ptr_elem_ty,
27547 parent.decl_ref_mut,
27548 );
28267 return beginComptimePtrMutationInner(
28268 sema,
28269 block,
28270 src,
28271 elem_ty,
28272 &elems[@intCast(usize, elem_ptr.index)],
28273 ptr_elem_ty,
28274 parent.mut_decl,
28275 );
28276 },
28277 else => unreachable,
2754928278 },
27550
27551 else => unreachable,
2755228279 }
2755328280 },
2755428281 else => {
......@@ -27565,28 +28292,29 @@ fn beginComptimePtrMutation(
2756528292 parent.ty,
2756628293 val_ptr,
2756728294 ptr_elem_ty,
27568 parent.decl_ref_mut,
28295 parent.mut_decl,
2756928296 );
2757028297 },
2757128298 },
2757228299 .reinterpret => |reinterpret| {
27573 if (!elem_ptr.elem_ty.hasWellDefinedLayout()) {
28300 if (!base_elem_ty.hasWellDefinedLayout(mod)) {
2757428301 // Even though the parent value type has well-defined memory layout, our
2757528302 // pointer type does not.
2757628303 return ComptimePtrMutationKit{
27577 .decl_ref_mut = parent.decl_ref_mut,
28304 .mut_decl = parent.mut_decl,
2757828305 .pointee = .bad_ptr_ty,
27579 .ty = elem_ptr.elem_ty,
28306 .ty = base_elem_ty,
2758028307 };
2758128308 }
2758228309
27583 const elem_abi_size_u64 = try sema.typeAbiSize(elem_ptr.elem_ty);
28310 const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty);
2758428311 const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64);
28312 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);
2758528313 return ComptimePtrMutationKit{
27586 .decl_ref_mut = parent.decl_ref_mut,
28314 .mut_decl = parent.mut_decl,
2758728315 .pointee = .{ .reinterpret = .{
2758828316 .val_ptr = reinterpret.val_ptr,
27589 .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_ptr.index,
28317 .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_idx,
2759028318 } },
2759128319 .ty = parent.ty,
2759228320 };
......@@ -27594,162 +28322,184 @@ fn beginComptimePtrMutation(
2759428322 .bad_decl_ty, .bad_ptr_ty => return parent,
2759528323 }
2759628324 },
27597 .field_ptr => {
27598 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
27599 const field_index = @intCast(u32, field_ptr.field_index);
28325 .field => |field_ptr| {
28326 const base_child_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
28327 const field_index = @intCast(u32, field_ptr.index);
2760028328
27601 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.container_ptr, field_ptr.container_ty);
28329 var parent = try sema.beginComptimePtrMutation(block, src, field_ptr.base.toValue(), base_child_ty);
2760228330 switch (parent.pointee) {
27603 .direct => |val_ptr| switch (val_ptr.tag()) {
27604 .undef => {
27605 // A struct or union has been initialized to undefined at comptime and now we
27606 // are for the first time setting a field. We must change the representation
27607 // of the struct/union from `undef` to `struct`/`union`.
27608 const arena = parent.beginArena(sema.mod);
27609 defer parent.finishArena(sema.mod);
27610
27611 switch (parent.ty.zigTypeTag()) {
27612 .Struct => {
27613 const fields = try arena.alloc(Value, parent.ty.structFieldCount());
27614 @memset(fields, Value.undef);
27615
27616 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
27617
27618 return beginComptimePtrMutationInner(
27619 sema,
27620 block,
27621 src,
27622 parent.ty.structFieldType(field_index),
27623 &fields[field_index],
27624 ptr_elem_ty,
27625 parent.decl_ref_mut,
27626 );
27627 },
27628 .Union => {
27629 const payload = try arena.create(Value.Payload.Union);
27630 payload.* = .{ .data = .{
27631 .tag = try Value.Tag.enum_field_index.create(arena, field_index),
27632 .val = Value.undef,
27633 } };
27634
27635 val_ptr.* = Value.initPayload(&payload.base);
27636
27637 return beginComptimePtrMutationInner(
27638 sema,
27639 block,
27640 src,
27641 parent.ty.structFieldType(field_index),
27642 &payload.data.val,
27643 ptr_elem_ty,
27644 parent.decl_ref_mut,
27645 );
27646 },
27647 .Pointer => {
27648 assert(parent.ty.isSlice());
27649 val_ptr.* = try Value.Tag.slice.create(arena, .{
27650 .ptr = Value.undef,
27651 .len = Value.undef,
27652 });
27653
27654 switch (field_index) {
27655 Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner(
27656 sema,
27657 block,
27658 src,
27659 parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)),
27660 &val_ptr.castTag(.slice).?.data.ptr,
27661 ptr_elem_ty,
27662 parent.decl_ref_mut,
27663 ),
27664 Value.Payload.Slice.len_index => return beginComptimePtrMutationInner(
27665 sema,
27666 block,
27667 src,
27668 Type.usize,
27669 &val_ptr.castTag(.slice).?.data.len,
27670 ptr_elem_ty,
27671 parent.decl_ref_mut,
27672 ),
27673
27674 else => unreachable,
27675 }
27676 },
27677 else => unreachable,
27678 }
27679 },
27680 .aggregate => return beginComptimePtrMutationInner(
27681 sema,
27682 block,
27683 src,
27684 parent.ty.structFieldType(field_index),
27685 &val_ptr.castTag(.aggregate).?.data[field_index],
27686 ptr_elem_ty,
27687 parent.decl_ref_mut,
27688 ),
27689
27690 .@"union" => {
27691 // We need to set the active field of the union.
27692 const arena = parent.beginArena(sema.mod);
27693 defer parent.finishArena(sema.mod);
27694
27695 const payload = &val_ptr.castTag(.@"union").?.data;
27696 payload.tag = try Value.Tag.enum_field_index.create(arena, field_index);
27697
28331 .direct => |val_ptr| switch (val_ptr.ip_index) {
28332 .empty_struct => {
28333 const duped = try sema.arena.create(Value);
28334 duped.* = val_ptr.*;
2769828335 return beginComptimePtrMutationInner(
2769928336 sema,
2770028337 block,
2770128338 src,
27702 parent.ty.structFieldType(field_index),
27703 &payload.val,
28339 parent.ty.structFieldType(field_index, mod),
28340 duped,
2770428341 ptr_elem_ty,
27705 parent.decl_ref_mut,
28342 parent.mut_decl,
2770628343 );
2770728344 },
27708 .slice => switch (field_index) {
27709 Value.Payload.Slice.ptr_index => return beginComptimePtrMutationInner(
28345 .none => switch (val_ptr.tag()) {
28346 .aggregate => return beginComptimePtrMutationInner(
2771028347 sema,
2771128348 block,
2771228349 src,
27713 parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)),
27714 &val_ptr.castTag(.slice).?.data.ptr,
28350 parent.ty.structFieldType(field_index, mod),
28351 &val_ptr.castTag(.aggregate).?.data[field_index],
2771528352 ptr_elem_ty,
27716 parent.decl_ref_mut,
28353 parent.mut_decl,
2771728354 ),
28355 .repeated => {
28356 const arena = sema.arena;
2771828357
27719 Value.Payload.Slice.len_index => return beginComptimePtrMutationInner(
27720 sema,
27721 block,
27722 src,
27723 Type.usize,
27724 &val_ptr.castTag(.slice).?.data.len,
27725 ptr_elem_ty,
27726 parent.decl_ref_mut,
27727 ),
28358 const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod));
28359 @memset(elems, val_ptr.castTag(.repeated).?.data);
28360 val_ptr.* = try Value.Tag.aggregate.create(arena, elems);
28361
28362 return beginComptimePtrMutationInner(
28363 sema,
28364 block,
28365 src,
28366 parent.ty.structFieldType(field_index, mod),
28367 &elems[field_index],
28368 ptr_elem_ty,
28369 parent.mut_decl,
28370 );
28371 },
28372 .@"union" => {
28373 // We need to set the active field of the union.
28374 const union_tag_ty = base_child_ty.unionTagTypeHypothetical(mod);
2772828375
28376 const payload = &val_ptr.castTag(.@"union").?.data;
28377 payload.tag = try mod.enumValueFieldIndex(union_tag_ty, field_index);
28378
28379 return beginComptimePtrMutationInner(
28380 sema,
28381 block,
28382 src,
28383 parent.ty.structFieldType(field_index, mod),
28384 &payload.val,
28385 ptr_elem_ty,
28386 parent.mut_decl,
28387 );
28388 },
28389 .slice => switch (field_index) {
28390 Value.slice_ptr_index => return beginComptimePtrMutationInner(
28391 sema,
28392 block,
28393 src,
28394 parent.ty.slicePtrFieldType(mod),
28395 &val_ptr.castTag(.slice).?.data.ptr,
28396 ptr_elem_ty,
28397 parent.mut_decl,
28398 ),
28399
28400 Value.slice_len_index => return beginComptimePtrMutationInner(
28401 sema,
28402 block,
28403 src,
28404 Type.usize,
28405 &val_ptr.castTag(.slice).?.data.len,
28406 ptr_elem_ty,
28407 parent.mut_decl,
28408 ),
28409
28410 else => unreachable,
28411 },
2772928412 else => unreachable,
2773028413 },
27731
27732 .empty_struct_value => {
27733 const duped = try sema.arena.create(Value);
27734 duped.* = Value.initTag(.the_only_possible_value);
27735 return beginComptimePtrMutationInner(
27736 sema,
27737 block,
27738 src,
27739 parent.ty.structFieldType(field_index),
27740 duped,
27741 ptr_elem_ty,
27742 parent.decl_ref_mut,
27743 );
28414 else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) {
28415 .undef => {
28416 // A struct or union has been initialized to undefined at comptime and now we
28417 // are for the first time setting a field. We must change the representation
28418 // of the struct/union from `undef` to `struct`/`union`.
28419 const arena = sema.arena;
28420
28421 switch (parent.ty.zigTypeTag(mod)) {
28422 .Struct => {
28423 const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod));
28424 for (fields, 0..) |*field, i| field.* = (try mod.intern(.{
28425 .undef = parent.ty.structFieldType(i, mod).toIntern(),
28426 })).toValue();
28427
28428 val_ptr.* = try Value.Tag.aggregate.create(arena, fields);
28429
28430 return beginComptimePtrMutationInner(
28431 sema,
28432 block,
28433 src,
28434 parent.ty.structFieldType(field_index, mod),
28435 &fields[field_index],
28436 ptr_elem_ty,
28437 parent.mut_decl,
28438 );
28439 },
28440 .Union => {
28441 const payload = try arena.create(Value.Payload.Union);
28442 const tag_ty = parent.ty.unionTagTypeHypothetical(mod);
28443 const payload_ty = parent.ty.structFieldType(field_index, mod);
28444 payload.* = .{ .data = .{
28445 .tag = try mod.enumValueFieldIndex(tag_ty, field_index),
28446 .val = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
28447 } };
28448
28449 val_ptr.* = Value.initPayload(&payload.base);
28450
28451 return beginComptimePtrMutationInner(
28452 sema,
28453 block,
28454 src,
28455 payload_ty,
28456 &payload.data.val,
28457 ptr_elem_ty,
28458 parent.mut_decl,
28459 );
28460 },
28461 .Pointer => {
28462 assert(parent.ty.isSlice(mod));
28463 const ptr_ty = parent.ty.slicePtrFieldType(mod);
28464 val_ptr.* = try Value.Tag.slice.create(arena, .{
28465 .ptr = (try mod.intern(.{ .undef = ptr_ty.toIntern() })).toValue(),
28466 .len = (try mod.intern(.{ .undef = .usize_type })).toValue(),
28467 });
28468
28469 switch (field_index) {
28470 Value.slice_ptr_index => return beginComptimePtrMutationInner(
28471 sema,
28472 block,
28473 src,
28474 ptr_ty,
28475 &val_ptr.castTag(.slice).?.data.ptr,
28476 ptr_elem_ty,
28477 parent.mut_decl,
28478 ),
28479 Value.slice_len_index => return beginComptimePtrMutationInner(
28480 sema,
28481 block,
28482 src,
28483 Type.usize,
28484 &val_ptr.castTag(.slice).?.data.len,
28485 ptr_elem_ty,
28486 parent.mut_decl,
28487 ),
28488
28489 else => unreachable,
28490 }
28491 },
28492 else => unreachable,
28493 }
28494 },
28495 else => unreachable,
2774428496 },
27745
27746 else => unreachable,
2774728497 },
2774828498 .reinterpret => |reinterpret| {
27749 const field_offset_u64 = field_ptr.container_ty.structFieldOffset(field_index, target);
28499 const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod);
2775028500 const field_offset = try sema.usizeCast(block, src, field_offset_u64);
2775128501 return ComptimePtrMutationKit{
27752 .decl_ref_mut = parent.decl_ref_mut,
28502 .mut_decl = parent.mut_decl,
2775328503 .pointee = .{ .reinterpret = .{
2775428504 .val_ptr = reinterpret.val_ptr,
2775528505 .byte_offset = reinterpret.byte_offset + field_offset,
......@@ -27760,106 +28510,6 @@ fn beginComptimePtrMutation(
2776028510 .bad_decl_ty, .bad_ptr_ty => return parent,
2776128511 }
2776228512 },
27763 .eu_payload_ptr => {
27764 const eu_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
27765 var parent = try sema.beginComptimePtrMutation(block, src, eu_ptr.container_ptr, eu_ptr.container_ty);
27766 switch (parent.pointee) {
27767 .direct => |val_ptr| {
27768 const payload_ty = parent.ty.errorUnionPayload();
27769 switch (val_ptr.tag()) {
27770 else => {
27771 // An error union has been initialized to undefined at comptime and now we
27772 // are for the first time setting the payload. We must change the
27773 // representation of the error union from `undef` to `opt_payload`.
27774 const arena = parent.beginArena(sema.mod);
27775 defer parent.finishArena(sema.mod);
27776
27777 const payload = try arena.create(Value.Payload.SubValue);
27778 payload.* = .{
27779 .base = .{ .tag = .eu_payload },
27780 .data = Value.undef,
27781 };
27782
27783 val_ptr.* = Value.initPayload(&payload.base);
27784
27785 return ComptimePtrMutationKit{
27786 .decl_ref_mut = parent.decl_ref_mut,
27787 .pointee = .{ .direct = &payload.data },
27788 .ty = payload_ty,
27789 };
27790 },
27791 .eu_payload => return ComptimePtrMutationKit{
27792 .decl_ref_mut = parent.decl_ref_mut,
27793 .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data },
27794 .ty = payload_ty,
27795 },
27796 }
27797 },
27798 .bad_decl_ty, .bad_ptr_ty => return parent,
27799 // Even though the parent value type has well-defined memory layout, our
27800 // pointer type does not.
27801 .reinterpret => return ComptimePtrMutationKit{
27802 .decl_ref_mut = parent.decl_ref_mut,
27803 .pointee = .bad_ptr_ty,
27804 .ty = eu_ptr.container_ty,
27805 },
27806 }
27807 },
27808 .opt_payload_ptr => {
27809 const opt_ptr = if (ptr_val.castTag(.opt_payload_ptr)) |some| some.data else {
27810 return sema.beginComptimePtrMutation(block, src, ptr_val, try ptr_elem_ty.optionalChildAlloc(sema.arena));
27811 };
27812 var parent = try sema.beginComptimePtrMutation(block, src, opt_ptr.container_ptr, opt_ptr.container_ty);
27813 switch (parent.pointee) {
27814 .direct => |val_ptr| {
27815 const payload_ty = try parent.ty.optionalChildAlloc(sema.arena);
27816 switch (val_ptr.tag()) {
27817 .undef, .null_value => {
27818 // An optional has been initialized to undefined at comptime and now we
27819 // are for the first time setting the payload. We must change the
27820 // representation of the optional from `undef` to `opt_payload`.
27821 const arena = parent.beginArena(sema.mod);
27822 defer parent.finishArena(sema.mod);
27823
27824 const payload = try arena.create(Value.Payload.SubValue);
27825 payload.* = .{
27826 .base = .{ .tag = .opt_payload },
27827 .data = Value.undef,
27828 };
27829
27830 val_ptr.* = Value.initPayload(&payload.base);
27831
27832 return ComptimePtrMutationKit{
27833 .decl_ref_mut = parent.decl_ref_mut,
27834 .pointee = .{ .direct = &payload.data },
27835 .ty = payload_ty,
27836 };
27837 },
27838 .opt_payload => return ComptimePtrMutationKit{
27839 .decl_ref_mut = parent.decl_ref_mut,
27840 .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },
27841 .ty = payload_ty,
27842 },
27843
27844 else => return ComptimePtrMutationKit{
27845 .decl_ref_mut = parent.decl_ref_mut,
27846 .pointee = .{ .direct = val_ptr },
27847 .ty = payload_ty,
27848 },
27849 }
27850 },
27851 .bad_decl_ty, .bad_ptr_ty => return parent,
27852 // Even though the parent value type has well-defined memory layout, our
27853 // pointer type does not.
27854 .reinterpret => return ComptimePtrMutationKit{
27855 .decl_ref_mut = parent.decl_ref_mut,
27856 .pointee = .bad_ptr_ty,
27857 .ty = opt_ptr.container_ty,
27858 },
27859 }
27860 },
27861 .decl_ref => unreachable, // isComptimeMutablePtr() has been checked already
27862 else => unreachable,
2786328513 }
2786428514}
2786528515
......@@ -27870,46 +28520,50 @@ fn beginComptimePtrMutationInner(
2787028520 decl_ty: Type,
2787128521 decl_val: *Value,
2787228522 ptr_elem_ty: Type,
27873 decl_ref_mut: Value.Payload.DeclRefMut.Data,
28523 mut_decl: InternPool.Key.Ptr.Addr.MutDecl,
2787428524) CompileError!ComptimePtrMutationKit {
27875 const target = sema.mod.getTarget();
28525 const mod = sema.mod;
28526 const target = mod.getTarget();
2787628527 const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok;
28528
28529 decl_val.* = try decl_val.unintern(sema.arena, mod);
28530
2787728531 if (coerce_ok) {
2787828532 return ComptimePtrMutationKit{
27879 .decl_ref_mut = decl_ref_mut,
28533 .mut_decl = mut_decl,
2788028534 .pointee = .{ .direct = decl_val },
2788128535 .ty = decl_ty,
2788228536 };
2788328537 }
2788428538
2788528539 // Handle the case that the decl is an array and we're actually trying to point to an element.
27886 if (decl_ty.isArrayOrVector()) {
27887 const decl_elem_ty = decl_ty.childType();
28540 if (decl_ty.isArrayOrVector(mod)) {
28541 const decl_elem_ty = decl_ty.childType(mod);
2788828542 if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) {
2788928543 return ComptimePtrMutationKit{
27890 .decl_ref_mut = decl_ref_mut,
28544 .mut_decl = mut_decl,
2789128545 .pointee = .{ .direct = decl_val },
2789228546 .ty = decl_ty,
2789328547 };
2789428548 }
2789528549 }
2789628550
27897 if (!decl_ty.hasWellDefinedLayout()) {
28551 if (!decl_ty.hasWellDefinedLayout(mod)) {
2789828552 return ComptimePtrMutationKit{
27899 .decl_ref_mut = decl_ref_mut,
27900 .pointee = .{ .bad_decl_ty = {} },
28553 .mut_decl = mut_decl,
28554 .pointee = .bad_decl_ty,
2790128555 .ty = decl_ty,
2790228556 };
2790328557 }
27904 if (!ptr_elem_ty.hasWellDefinedLayout()) {
28558 if (!ptr_elem_ty.hasWellDefinedLayout(mod)) {
2790528559 return ComptimePtrMutationKit{
27906 .decl_ref_mut = decl_ref_mut,
27907 .pointee = .{ .bad_ptr_ty = {} },
28560 .mut_decl = mut_decl,
28561 .pointee = .bad_ptr_ty,
2790828562 .ty = ptr_elem_ty,
2790928563 };
2791028564 }
2791128565 return ComptimePtrMutationKit{
27912 .decl_ref_mut = decl_ref_mut,
28566 .mut_decl = mut_decl,
2791328567 .pointee = .{ .reinterpret = .{
2791428568 .val_ptr = decl_val,
2791528569 .byte_offset = 0,
......@@ -27951,237 +28605,227 @@ fn beginComptimePtrLoad(
2795128605 ptr_val: Value,
2795228606 maybe_array_ty: ?Type,
2795328607) ComptimePtrLoadError!ComptimePtrLoadKit {
27954 const target = sema.mod.getTarget();
27955 var deref: ComptimePtrLoadKit = switch (ptr_val.tag()) {
27956 .decl_ref,
27957 .decl_ref_mut,
27958 => blk: {
27959 const decl_index = switch (ptr_val.tag()) {
27960 .decl_ref => ptr_val.castTag(.decl_ref).?.data,
27961 .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,
27962 else => unreachable,
27963 };
27964 const is_mutable = ptr_val.tag() == .decl_ref_mut;
27965 const decl = sema.mod.declPtr(decl_index);
27966 const decl_tv = try decl.typedValue();
27967 if (decl_tv.val.tag() == .variable) return error.RuntimeLoad;
27968
27969 const layout_defined = decl.ty.hasWellDefinedLayout();
27970 break :blk ComptimePtrLoadKit{
27971 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
27972 .pointee = decl_tv,
27973 .is_mutable = is_mutable,
27974 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
27975 };
27976 },
27977
27978 .elem_ptr => blk: {
27979 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
27980 const elem_ty = elem_ptr.elem_ty;
27981 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.array_ptr, null);
27982
27983 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
27984 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
27985 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
27986 if (elem_ptr.array_ptr.castTag(.elem_ptr)) |parent_elem_ptr| {
27987 assert(!(parent_elem_ptr.data.elem_ty.eql(elem_ty, sema.mod)));
27988 }
27989
27990 if (elem_ptr.index != 0) {
27991 if (elem_ty.hasWellDefinedLayout()) {
27992 if (deref.parent) |*parent| {
27993 // Update the byte offset (in-place)
27994 const elem_size = try sema.typeAbiSize(elem_ty);
27995 const offset = parent.byte_offset + elem_size * elem_ptr.index;
27996 parent.byte_offset = try sema.usizeCast(block, src, offset);
27997 }
27998 } else {
27999 deref.parent = null;
28000 deref.ty_without_well_defined_layout = elem_ty;
28001 }
28002 }
28003
28004 // If we're loading an elem_ptr that was derived from a different type
28005 // than the true type of the underlying decl, we cannot deref directly
28006 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector()) x: {
28007 const deref_elem_ty = deref.pointee.?.ty.childType();
28008 break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or
28009 (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;
28010 } else false;
28011 if (!ty_matches) {
28012 deref.pointee = null;
28013 break :blk deref;
28014 }
28015
28016 var array_tv = deref.pointee.?;
28017 const check_len = array_tv.ty.arrayLenIncludingSentinel();
28018 if (maybe_array_ty) |load_ty| {
28019 // It's possible that we're loading a [N]T, in which case we'd like to slice
28020 // the pointee array directly from our parent array.
28021 if (load_ty.isArrayOrVector() and load_ty.childType().eql(elem_ty, sema.mod)) {
28022 const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel());
28023 deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{
28024 .ty = try Type.array(sema.arena, N, null, elem_ty, sema.mod),
28025 .val = try array_tv.val.sliceArray(sema.mod, sema.arena, elem_ptr.index, elem_ptr.index + N),
28026 } else null;
28027 break :blk deref;
28028 }
28029 }
28030
28031 if (elem_ptr.index >= check_len) {
28032 deref.pointee = null;
28033 break :blk deref;
28034 }
28035 if (elem_ptr.index == check_len - 1) {
28036 if (array_tv.ty.sentinel()) |sent| {
28037 deref.pointee = TypedValue{
28038 .ty = elem_ty,
28039 .val = sent,
28040 };
28041 break :blk deref;
28042 }
28043 }
28044 deref.pointee = TypedValue{
28045 .ty = elem_ty,
28046 .val = try array_tv.val.elemValue(sema.mod, sema.arena, elem_ptr.index),
28047 };
28048 break :blk deref;
28049 },
28050
28051 .slice => blk: {
28052 const slice = ptr_val.castTag(.slice).?.data;
28053 break :blk try sema.beginComptimePtrLoad(block, src, slice.ptr, null);
28054 },
28608 const mod = sema.mod;
28609 const target = mod.getTarget();
2805528610
28056 .field_ptr => blk: {
28057 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
28058 const field_index = @intCast(u32, field_ptr.field_index);
28059 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.container_ptr, field_ptr.container_ty);
28611 var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {
28612 .ptr => |ptr| switch (ptr.addr) {
28613 .decl, .mut_decl => blk: {
28614 const decl_index = switch (ptr.addr) {
28615 .decl => |decl| decl,
28616 .mut_decl => |mut_decl| mut_decl.decl,
28617 else => unreachable,
28618 };
28619 const is_mutable = ptr.addr == .mut_decl;
28620 const decl = mod.declPtr(decl_index);
28621 const decl_tv = try decl.typedValue();
28622 if (decl.val.getVariable(mod) != null) return error.RuntimeLoad;
28623
28624 const layout_defined = decl.ty.hasWellDefinedLayout(mod);
28625 break :blk ComptimePtrLoadKit{
28626 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
28627 .pointee = decl_tv,
28628 .is_mutable = is_mutable,
28629 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
28630 };
28631 },
28632 .int => return error.RuntimeLoad,
28633 .eu_payload, .opt_payload => |container_ptr| blk: {
28634 const container_ty = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);
28635 const payload_ty = switch (ptr.addr) {
28636 .eu_payload => container_ty.errorUnionPayload(mod),
28637 .opt_payload => container_ty.optionalChild(mod),
28638 else => unreachable,
28639 };
28640 var deref = try sema.beginComptimePtrLoad(block, src, container_ptr.toValue(), container_ty);
2806028641
28061 if (field_ptr.container_ty.hasWellDefinedLayout()) {
28062 const struct_ty = field_ptr.container_ty.castTag(.@"struct");
28063 if (struct_ty != null and struct_ty.?.data.layout == .Packed) {
28064 // packed structs are not byte addressable
28642 // eu_payload and opt_payload never have a well-defined layout
28643 if (deref.parent != null) {
2806528644 deref.parent = null;
28066 } else if (deref.parent) |*parent| {
28067 // Update the byte offset (in-place)
28068 try sema.resolveTypeLayout(field_ptr.container_ty);
28069 const field_offset = field_ptr.container_ty.structFieldOffset(field_index, target);
28070 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
28645 deref.ty_without_well_defined_layout = container_ty;
28646 }
28647
28648 if (deref.pointee) |*tv| {
28649 const coerce_in_mem_ok =
28650 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28651 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28652 if (coerce_in_mem_ok) {
28653 const payload_val = switch (tv.val.ip_index) {
28654 .none => tv.val.cast(Value.Payload.SubValue).?.data,
28655 .null_value => return sema.fail(block, src, "attempt to use null value", .{}),
28656 else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
28657 .error_union => |error_union| switch (error_union.val) {
28658 .err_name => |err_name| return sema.fail(
28659 block,
28660 src,
28661 "attempt to unwrap error: {}",
28662 .{err_name.fmt(&mod.intern_pool)},
28663 ),
28664 .payload => |payload| payload,
28665 },
28666 .opt => |opt| switch (opt.val) {
28667 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28668 else => |payload| payload,
28669 },
28670 else => unreachable,
28671 }.toValue(),
28672 };
28673 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
28674 break :blk deref;
28675 }
2807128676 }
28072 } else {
28073 deref.parent = null;
28074 deref.ty_without_well_defined_layout = field_ptr.container_ty;
28075 }
28076
28077 const tv = deref.pointee orelse {
28078 deref.pointee = null;
28079 break :blk deref;
28080 };
28081 const coerce_in_mem_ok =
28082 (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28083 (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok;
28084 if (!coerce_in_mem_ok) {
2808528677 deref.pointee = null;
2808628678 break :blk deref;
28087 }
28088
28089 if (field_ptr.container_ty.isSlice()) {
28090 const slice_val = tv.val.castTag(.slice).?.data;
28091 deref.pointee = switch (field_index) {
28092 Value.Payload.Slice.ptr_index => TypedValue{
28093 .ty = field_ptr.container_ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)),
28094 .val = slice_val.ptr,
28095 },
28096 Value.Payload.Slice.len_index => TypedValue{
28097 .ty = Type.usize,
28098 .val = slice_val.len,
28099 },
28100 else => unreachable,
28101 };
28102 } else {
28103 const field_ty = field_ptr.container_ty.structFieldType(field_index);
28104 deref.pointee = TypedValue{
28105 .ty = field_ty,
28106 .val = tv.val.fieldValue(tv.ty, field_index),
28679 },
28680 .comptime_field => |comptime_field| blk: {
28681 const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
28682 break :blk ComptimePtrLoadKit{
28683 .parent = null,
28684 .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
28685 .is_mutable = false,
28686 .ty_without_well_defined_layout = field_ty,
2810728687 };
28108 }
28109 break :blk deref;
28110 },
28688 },
28689 .elem => |elem_ptr| blk: {
28690 const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);
28691 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
28692
28693 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
28694 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
28695 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
28696 switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
28697 .ptr => |base_ptr| switch (base_ptr.addr) {
28698 .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
28699 else => {},
28700 },
28701 else => {},
28702 }
2811128703
28112 .comptime_field_ptr => blk: {
28113 const comptime_field_ptr = ptr_val.castTag(.comptime_field_ptr).?.data;
28114 break :blk ComptimePtrLoadKit{
28115 .parent = null,
28116 .pointee = .{ .ty = comptime_field_ptr.field_ty, .val = comptime_field_ptr.field_val },
28117 .is_mutable = false,
28118 .ty_without_well_defined_layout = comptime_field_ptr.field_ty,
28119 };
28120 },
28704 if (elem_ptr.index != 0) {
28705 if (elem_ty.hasWellDefinedLayout(mod)) {
28706 if (deref.parent) |*parent| {
28707 // Update the byte offset (in-place)
28708 const elem_size = try sema.typeAbiSize(elem_ty);
28709 const offset = parent.byte_offset + elem_size * elem_ptr.index;
28710 parent.byte_offset = try sema.usizeCast(block, src, offset);
28711 }
28712 } else {
28713 deref.parent = null;
28714 deref.ty_without_well_defined_layout = elem_ty;
28715 }
28716 }
2812128717
28122 .opt_payload_ptr,
28123 .eu_payload_ptr,
28124 => blk: {
28125 const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;
28126 const payload_ty = switch (ptr_val.tag()) {
28127 .eu_payload_ptr => payload_ptr.container_ty.errorUnionPayload(),
28128 .opt_payload_ptr => try payload_ptr.container_ty.optionalChildAlloc(sema.arena),
28129 else => unreachable,
28130 };
28131 var deref = try sema.beginComptimePtrLoad(block, src, payload_ptr.container_ptr, payload_ptr.container_ty);
28718 // If we're loading an elem that was derived from a different type
28719 // than the true type of the underlying decl, we cannot deref directly
28720 const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: {
28721 const deref_elem_ty = deref.pointee.?.ty.childType(mod);
28722 break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or
28723 (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok;
28724 } else false;
28725 if (!ty_matches) {
28726 deref.pointee = null;
28727 break :blk deref;
28728 }
2813228729
28133 // eu_payload_ptr and opt_payload_ptr never have a well-defined layout
28134 if (deref.parent != null) {
28135 deref.parent = null;
28136 deref.ty_without_well_defined_layout = payload_ptr.container_ty;
28137 }
28730 var array_tv = deref.pointee.?;
28731 const check_len = array_tv.ty.arrayLenIncludingSentinel(mod);
28732 if (maybe_array_ty) |load_ty| {
28733 // It's possible that we're loading a [N]T, in which case we'd like to slice
28734 // the pointee array directly from our parent array.
28735 if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) {
28736 const N = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod));
28737 const elem_idx = try sema.usizeCast(block, src, elem_ptr.index);
28738 deref.pointee = if (elem_ptr.index + N <= check_len) TypedValue{
28739 .ty = try Type.array(sema.arena, N, null, elem_ty, mod),
28740 .val = try array_tv.val.sliceArray(mod, sema.arena, elem_idx, elem_idx + N),
28741 } else null;
28742 break :blk deref;
28743 }
28744 }
28745
28746 if (elem_ptr.index >= check_len) {
28747 deref.pointee = null;
28748 break :blk deref;
28749 }
28750 if (elem_ptr.index == check_len - 1) {
28751 if (array_tv.ty.sentinel(mod)) |sent| {
28752 deref.pointee = TypedValue{
28753 .ty = elem_ty,
28754 .val = sent,
28755 };
28756 break :blk deref;
28757 }
28758 }
28759 deref.pointee = TypedValue{
28760 .ty = elem_ty,
28761 .val = try array_tv.val.elemValue(mod, @intCast(usize, elem_ptr.index)),
28762 };
28763 break :blk deref;
28764 },
28765 .field => |field_ptr| blk: {
28766 const field_index = @intCast(u32, field_ptr.index);
28767 const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
28768 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
28769
28770 if (container_ty.hasWellDefinedLayout(mod)) {
28771 const struct_obj = mod.typeToStruct(container_ty);
28772 if (struct_obj != null and struct_obj.?.layout == .Packed) {
28773 // packed structs are not byte addressable
28774 deref.parent = null;
28775 } else if (deref.parent) |*parent| {
28776 // Update the byte offset (in-place)
28777 try sema.resolveTypeLayout(container_ty);
28778 const field_offset = container_ty.structFieldOffset(field_index, mod);
28779 parent.byte_offset = try sema.usizeCast(block, src, parent.byte_offset + field_offset);
28780 }
28781 } else {
28782 deref.parent = null;
28783 deref.ty_without_well_defined_layout = container_ty;
28784 }
2813828785
28139 if (deref.pointee) |*tv| {
28786 const tv = deref.pointee orelse {
28787 deref.pointee = null;
28788 break :blk deref;
28789 };
2814028790 const coerce_in_mem_ok =
28141 (try sema.coerceInMemoryAllowed(block, payload_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or
28142 (try sema.coerceInMemoryAllowed(block, tv.ty, payload_ptr.container_ty, false, target, src, src)) == .ok;
28143 if (coerce_in_mem_ok) {
28144 const payload_val = switch (ptr_val.tag()) {
28145 .eu_payload_ptr => if (tv.val.castTag(.eu_payload)) |some| some.data else {
28146 return sema.fail(block, src, "attempt to unwrap error: {s}", .{tv.val.castTag(.@"error").?.data.name});
28791 (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or
28792 (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok;
28793 if (!coerce_in_mem_ok) {
28794 deref.pointee = null;
28795 break :blk deref;
28796 }
28797
28798 if (container_ty.isSlice(mod)) {
28799 deref.pointee = switch (field_index) {
28800 Value.slice_ptr_index => TypedValue{
28801 .ty = container_ty.slicePtrFieldType(mod),
28802 .val = tv.val.slicePtr(mod),
2814728803 },
28148 .opt_payload_ptr => if (tv.val.castTag(.opt_payload)) |some| some.data else opt: {
28149 if (tv.val.isNull()) return sema.fail(block, src, "attempt to use null value", .{});
28150 break :opt tv.val;
28804 Value.slice_len_index => TypedValue{
28805 .ty = Type.usize,
28806 .val = mod.intern_pool.indexToKey(tv.val.toIntern()).ptr.len.toValue(),
2815128807 },
2815228808 else => unreachable,
2815328809 };
28154 tv.* = TypedValue{ .ty = payload_ty, .val = payload_val };
28155 break :blk deref;
28810 } else {
28811 const field_ty = container_ty.structFieldType(field_index, mod);
28812 deref.pointee = TypedValue{
28813 .ty = field_ty,
28814 .val = try tv.val.fieldValue(mod, field_index),
28815 };
2815628816 }
28157 }
28158 deref.pointee = null;
28159 break :blk deref;
28160 },
28161 .null_value => {
28162 return sema.fail(block, src, "attempt to use null value", .{});
28817 break :blk deref;
28818 },
2816328819 },
28164 .opt_payload => blk: {
28165 const opt_payload = ptr_val.castTag(.opt_payload).?.data;
28166 break :blk try sema.beginComptimePtrLoad(block, src, opt_payload, null);
28820 .opt => |opt| switch (opt.val) {
28821 .none => return sema.fail(block, src, "attempt to use null value", .{}),
28822 else => |payload| try sema.beginComptimePtrLoad(block, src, payload.toValue(), null),
2816728823 },
28168
28169 .zero,
28170 .one,
28171 .int_u64,
28172 .int_i64,
28173 .int_big_positive,
28174 .int_big_negative,
28175 .variable,
28176 .extern_fn,
28177 .function,
28178 => return error.RuntimeLoad,
28179
2818028824 else => unreachable,
2818128825 };
2818228826
2818328827 if (deref.pointee) |tv| {
28184 if (deref.parent == null and tv.ty.hasWellDefinedLayout()) {
28828 if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) {
2818528829 deref.parent = .{ .tv = tv, .byte_offset = 0 };
2818628830 }
2818728831 }
......@@ -28196,21 +28840,21 @@ fn bitCast(
2819628840 inst_src: LazySrcLoc,
2819728841 operand_src: ?LazySrcLoc,
2819828842) CompileError!Air.Inst.Ref {
28843 const mod = sema.mod;
2819928844 const dest_ty = try sema.resolveTypeFields(dest_ty_unresolved);
2820028845 try sema.resolveTypeLayout(dest_ty);
2820128846
2820228847 const old_ty = try sema.resolveTypeFields(sema.typeOf(inst));
2820328848 try sema.resolveTypeLayout(old_ty);
2820428849
28205 const target = sema.mod.getTarget();
28206 const dest_bits = dest_ty.bitSize(target);
28207 const old_bits = old_ty.bitSize(target);
28850 const dest_bits = dest_ty.bitSize(mod);
28851 const old_bits = old_ty.bitSize(mod);
2820828852
2820928853 if (old_bits != dest_bits) {
2821028854 return sema.fail(block, inst_src, "@bitCast size mismatch: destination type '{}' has {d} bits but source type '{}' has {d} bits", .{
28211 dest_ty.fmt(sema.mod),
28855 dest_ty.fmt(mod),
2821228856 dest_bits,
28213 old_ty.fmt(sema.mod),
28857 old_ty.fmt(mod),
2821428858 old_bits,
2821528859 });
2821628860 }
......@@ -28233,20 +28877,21 @@ fn bitCastVal(
2823328877 new_ty: Type,
2823428878 buffer_offset: usize,
2823528879) !?Value {
28236 const target = sema.mod.getTarget();
28237 if (old_ty.eql(new_ty, sema.mod)) return val;
28880 const mod = sema.mod;
28881 if (old_ty.eql(new_ty, mod)) return val;
2823828882
2823928883 // For types with well-defined memory layouts, we serialize them a byte buffer,
2824028884 // then deserialize to the new type.
28241 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));
28885 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(mod));
2824228886 const buffer = try sema.gpa.alloc(u8, abi_size);
2824328887 defer sema.gpa.free(buffer);
28244 val.writeToMemory(old_ty, sema.mod, buffer) catch |err| switch (err) {
28888 val.writeToMemory(old_ty, mod, buffer) catch |err| switch (err) {
28889 error.OutOfMemory => return error.OutOfMemory,
2824528890 error.ReinterpretDeclRef => return null,
2824628891 error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already
28247 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{old_ty.fmt(sema.mod)}),
28892 error.Unimplemented => return sema.fail(block, src, "TODO: implement writeToMemory for type '{}'", .{old_ty.fmt(mod)}),
2824828893 };
28249 return try Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);
28894 return try Value.readFromMemory(new_ty, mod, buffer[buffer_offset..], sema.arena);
2825028895}
2825128896
2825228897fn coerceArrayPtrToSlice(
......@@ -28256,25 +28901,32 @@ fn coerceArrayPtrToSlice(
2825628901 inst: Air.Inst.Ref,
2825728902 inst_src: LazySrcLoc,
2825828903) CompileError!Air.Inst.Ref {
28904 const mod = sema.mod;
2825928905 if (try sema.resolveMaybeUndefVal(inst)) |val| {
2826028906 const ptr_array_ty = sema.typeOf(inst);
28261 const array_ty = ptr_array_ty.childType();
28262 const slice_val = try Value.Tag.slice.create(sema.arena, .{
28263 .ptr = val,
28264 .len = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen()),
28265 });
28266 return sema.addConstant(dest_ty, slice_val);
28907 const array_ty = ptr_array_ty.childType(mod);
28908 const slice_val = try mod.intern(.{ .ptr = .{
28909 .ty = dest_ty.toIntern(),
28910 .addr = switch (mod.intern_pool.indexToKey(val.toIntern())) {
28911 .undef => .{ .int = try mod.intern(.{ .undef = .usize_type }) },
28912 .ptr => |ptr| ptr.addr,
28913 else => unreachable,
28914 },
28915 .len = (try mod.intValue(Type.usize, array_ty.arrayLen(mod))).toIntern(),
28916 } });
28917 return sema.addConstant(dest_ty, slice_val.toValue());
2826728918 }
2826828919 try sema.requireRuntimeBlock(block, inst_src, null);
2826928920 return block.addTyOp(.array_to_slice, dest_ty, inst);
2827028921}
2827128922
2827228923fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_result: *InMemoryCoercionResult) bool {
28273 const dest_info = dest_ty.ptrInfo().data;
28274 const inst_info = inst_ty.ptrInfo().data;
28275 const len0 = (inst_info.pointee_type.zigTypeTag() == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel() == 0 or
28276 (inst_info.pointee_type.arrayLen() == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or
28277 (inst_info.pointee_type.isTuple() and inst_info.pointee_type.structFieldCount() == 0);
28924 const mod = sema.mod;
28925 const dest_info = dest_ty.ptrInfo(mod);
28926 const inst_info = inst_ty.ptrInfo(mod);
28927 const len0 = (inst_info.pointee_type.zigTypeTag(mod) == .Array and (inst_info.pointee_type.arrayLenIncludingSentinel(mod) == 0 or
28928 (inst_info.pointee_type.arrayLen(mod) == 0 and dest_info.sentinel == null and dest_info.size != .C and dest_info.size != .Many))) or
28929 (inst_info.pointee_type.isTuple(mod) and inst_info.pointee_type.structFieldCount(mod) == 0);
2827828930
2827928931 const ok_cv_qualifiers =
2828028932 ((inst_info.mutable or !dest_info.mutable) or len0) and
......@@ -28298,17 +28950,16 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
2829828950 }
2829928951 if (inst_info.@"align" == 0 and dest_info.@"align" == 0) return true;
2830028952 if (len0) return true;
28301 const target = sema.mod.getTarget();
2830228953
2830328954 const inst_align = if (inst_info.@"align" != 0)
2830428955 inst_info.@"align"
2830528956 else
28306 inst_info.pointee_type.abiAlignment(target);
28957 inst_info.pointee_type.abiAlignment(mod);
2830728958
2830828959 const dest_align = if (dest_info.@"align" != 0)
2830928960 dest_info.@"align"
2831028961 else
28311 dest_info.pointee_type.abiAlignment(target);
28962 dest_info.pointee_type.abiAlignment(mod);
2831228963
2831328964 if (dest_align > inst_align) {
2831428965 in_memory_result.* = .{ .ptr_alignment = .{
......@@ -28327,26 +28978,30 @@ fn coerceCompatiblePtrs(
2832728978 inst: Air.Inst.Ref,
2832828979 inst_src: LazySrcLoc,
2832928980) !Air.Inst.Ref {
28981 const mod = sema.mod;
2833028982 const inst_ty = sema.typeOf(inst);
2833128983 if (try sema.resolveMaybeUndefVal(inst)) |val| {
28332 if (!val.isUndef() and val.isNull() and !dest_ty.isAllowzeroPtr()) {
28984 if (!val.isUndef(mod) and val.isNull(mod) and !dest_ty.isAllowzeroPtr(mod)) {
2833328985 return sema.fail(block, inst_src, "null pointer casted to type '{}'", .{dest_ty.fmt(sema.mod)});
2833428986 }
2833528987 // The comptime Value representation is compatible with both types.
28336 return sema.addConstant(dest_ty, val);
28988 return sema.addConstant(
28989 dest_ty,
28990 try mod.getCoerced((try val.intern(inst_ty, mod)).toValue(), dest_ty),
28991 );
2833728992 }
2833828993 try sema.requireRuntimeBlock(block, inst_src, null);
28339 const inst_allows_zero = inst_ty.zigTypeTag() != .Pointer or inst_ty.ptrAllowsZero();
28340 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero() and
28341 (try sema.typeHasRuntimeBits(dest_ty.elemType2()) or dest_ty.elemType2().zigTypeTag() == .Fn))
28994 const inst_allows_zero = inst_ty.zigTypeTag(mod) != .Pointer or inst_ty.ptrAllowsZero(mod);
28995 if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(mod) and
28996 (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn))
2834228997 {
28343 const actual_ptr = if (inst_ty.isSlice())
28998 const actual_ptr = if (inst_ty.isSlice(mod))
2834428999 try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty)
2834529000 else
2834629001 inst;
2834729002 const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr);
2834829003 const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize);
28349 const ok = if (inst_ty.isSlice()) ok: {
29004 const ok = if (inst_ty.isSlice(mod)) ok: {
2835029005 const len = try sema.analyzeSliceLen(block, inst_src, inst);
2835129006 const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize);
2835229007 break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero);
......@@ -28364,9 +29019,11 @@ fn coerceEnumToUnion(
2836429019 inst: Air.Inst.Ref,
2836529020 inst_src: LazySrcLoc,
2836629021) !Air.Inst.Ref {
29022 const mod = sema.mod;
29023 const ip = &mod.intern_pool;
2836729024 const inst_ty = sema.typeOf(inst);
2836829025
28369 const tag_ty = union_ty.unionTagType() orelse {
29026 const tag_ty = union_ty.unionTagType(mod) orelse {
2837029027 const msg = msg: {
2837129028 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{
2837229029 union_ty.fmt(sema.mod), inst_ty.fmt(sema.mod),
......@@ -28393,16 +29050,18 @@ fn coerceEnumToUnion(
2839329050 return sema.failWithOwnedErrorMsg(msg);
2839429051 };
2839529052
28396 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
29053 const union_obj = mod.typeToUnion(union_ty).?;
2839729054 const field = union_obj.fields.values()[field_index];
2839829055 const field_ty = try sema.resolveTypeFields(field.ty);
28399 if (field_ty.zigTypeTag() == .NoReturn) {
29056 if (field_ty.zigTypeTag(mod) == .NoReturn) {
2840029057 const msg = msg: {
2840129058 const msg = try sema.errMsg(block, inst_src, "cannot initialize 'noreturn' field of union", .{});
2840229059 errdefer msg.destroy(sema.gpa);
2840329060
2840429061 const field_name = union_obj.fields.keys()[field_index];
28405 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
29062 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
29063 field_name.fmt(ip),
29064 });
2840629065 try sema.addDeclaredHereNote(msg, union_ty);
2840729066 break :msg msg;
2840829067 };
......@@ -28411,27 +29070,27 @@ fn coerceEnumToUnion(
2841129070 const opv = (try sema.typeHasOnePossibleValue(field_ty)) orelse {
2841229071 const msg = msg: {
2841329072 const field_name = union_obj.fields.keys()[field_index];
28414 const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{s}'", .{
28415 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod), field_ty.fmt(sema.mod), field_name,
29073 const msg = try sema.errMsg(block, inst_src, "coercion from enum '{}' to union '{}' must initialize '{}' field '{}'", .{
29074 inst_ty.fmt(sema.mod), union_ty.fmt(sema.mod),
29075 field_ty.fmt(sema.mod), field_name.fmt(ip),
2841629076 });
2841729077 errdefer msg.destroy(sema.gpa);
2841829078
28419 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' declared here", .{field_name});
29079 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' declared here", .{
29080 field_name.fmt(ip),
29081 });
2842029082 try sema.addDeclaredHereNote(msg, union_ty);
2842129083 break :msg msg;
2842229084 };
2842329085 return sema.failWithOwnedErrorMsg(msg);
2842429086 };
2842529087
28426 return sema.addConstant(union_ty, try Value.Tag.@"union".create(sema.arena, .{
28427 .tag = val,
28428 .val = opv,
28429 }));
29088 return sema.addConstant(union_ty, try mod.unionValue(union_ty, val, opv));
2843029089 }
2843129090
2843229091 try sema.requireRuntimeBlock(block, inst_src, null);
2843329092
28434 if (tag_ty.isNonexhaustiveEnum()) {
29093 if (tag_ty.isNonexhaustiveEnum(mod)) {
2843529094 const msg = msg: {
2843629095 const msg = try sema.errMsg(block, inst_src, "runtime coercion to union '{}' from non-exhaustive enum", .{
2843729096 union_ty.fmt(sema.mod),
......@@ -28443,13 +29102,13 @@ fn coerceEnumToUnion(
2844329102 return sema.failWithOwnedErrorMsg(msg);
2844429103 }
2844529104
28446 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
29105 const union_obj = mod.typeToUnion(union_ty).?;
2844729106 {
2844829107 var msg: ?*Module.ErrorMsg = null;
2844929108 errdefer if (msg) |some| some.destroy(sema.gpa);
2845029109
2845129110 for (union_obj.fields.values(), 0..) |field, i| {
28452 if (field.ty.zigTypeTag() == .NoReturn) {
29111 if (field.ty.zigTypeTag(mod) == .NoReturn) {
2845329112 const err_msg = msg orelse try sema.errMsg(
2845429113 block,
2845529114 inst_src,
......@@ -28469,7 +29128,7 @@ fn coerceEnumToUnion(
2846929128 }
2847029129
2847129130 // If the union has all fields 0 bits, the union value is just the enum value.
28472 if (union_ty.unionHasAllZeroBitFieldTypes()) {
29131 if (union_ty.unionHasAllZeroBitFieldTypes(mod)) {
2847329132 return block.addBitCast(union_ty, enum_tag);
2847429133 }
2847529134
......@@ -28487,8 +29146,11 @@ fn coerceEnumToUnion(
2848729146 while (it.next()) |field| : (field_index += 1) {
2848829147 const field_name = field.key_ptr.*;
2848929148 const field_ty = field.value_ptr.ty;
28490 if (!field_ty.hasRuntimeBits()) continue;
28491 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{s}' has type '{}'", .{ field_name, field_ty.fmt(sema.mod) });
29149 if (!(try sema.typeHasRuntimeBits(field_ty))) continue;
29150 try sema.addFieldErrNote(union_ty, field_index, msg, "field '{}' has type '{}'", .{
29151 field_name.fmt(ip),
29152 field_ty.fmt(sema.mod),
29153 });
2849229154 }
2849329155 try sema.addDeclaredHereNote(msg, union_ty);
2849429156 break :msg msg;
......@@ -28504,36 +29166,55 @@ fn coerceAnonStructToUnion(
2850429166 inst: Air.Inst.Ref,
2850529167 inst_src: LazySrcLoc,
2850629168) !Air.Inst.Ref {
29169 const mod = sema.mod;
2850729170 const inst_ty = sema.typeOf(inst);
28508 const field_count = inst_ty.structFieldCount();
28509 if (field_count != 1) {
28510 const msg = msg: {
28511 const msg = if (field_count > 1) try sema.errMsg(
28512 block,
28513 inst_src,
28514 "cannot initialize multiple union fields at once; unions can only have one active field",
28515 .{},
28516 ) else try sema.errMsg(
28517 block,
28518 inst_src,
28519 "union initializer must initialize one field",
28520 .{},
28521 );
28522 errdefer msg.destroy(sema.gpa);
29171 const field_info: union(enum) {
29172 name: InternPool.NullTerminatedString,
29173 count: usize,
29174 } = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
29175 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
29176 .{ .name = anon_struct_type.names[0] }
29177 else
29178 .{ .count = anon_struct_type.names.len },
29179 .struct_type => |struct_type| name: {
29180 const field_names = mod.structPtrUnwrap(struct_type.index).?.fields.keys();
29181 break :name if (field_names.len == 1)
29182 .{ .name = field_names[0] }
29183 else
29184 .{ .count = field_names.len };
29185 },
29186 else => unreachable,
29187 };
29188 switch (field_info) {
29189 .name => |field_name| {
29190 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
29191 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
29192 },
29193 .count => |field_count| {
29194 assert(field_count != 1);
29195 const msg = msg: {
29196 const msg = if (field_count > 1) try sema.errMsg(
29197 block,
29198 inst_src,
29199 "cannot initialize multiple union fields at once; unions can only have one active field",
29200 .{},
29201 ) else try sema.errMsg(
29202 block,
29203 inst_src,
29204 "union initializer must initialize one field",
29205 .{},
29206 );
29207 errdefer msg.destroy(sema.gpa);
2852329208
28524 // TODO add notes for where the anon struct was created to point out
28525 // the extra fields.
29209 // TODO add notes for where the anon struct was created to point out
29210 // the extra fields.
2852629211
28527 try sema.addDeclaredHereNote(msg, union_ty);
28528 break :msg msg;
28529 };
28530 return sema.failWithOwnedErrorMsg(msg);
29212 try sema.addDeclaredHereNote(msg, union_ty);
29213 break :msg msg;
29214 };
29215 return sema.failWithOwnedErrorMsg(msg);
29216 },
2853129217 }
28532
28533 const anon_struct = inst_ty.castTag(.anon_struct).?.data;
28534 const field_name = anon_struct.names[0];
28535 const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
28536 return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
2853729218}
2853829219
2853929220fn coerceAnonStructToUnionPtrs(
......@@ -28544,7 +29225,8 @@ fn coerceAnonStructToUnionPtrs(
2854429225 ptr_anon_struct: Air.Inst.Ref,
2854529226 anon_struct_src: LazySrcLoc,
2854629227) !Air.Inst.Ref {
28547 const union_ty = ptr_union_ty.childType();
29228 const mod = sema.mod;
29229 const union_ty = ptr_union_ty.childType(mod);
2854829230 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);
2854929231 const union_inst = try sema.coerceAnonStructToUnion(block, union_ty, union_ty_src, anon_struct, anon_struct_src);
2855029232 return sema.analyzeRef(block, union_ty_src, union_inst);
......@@ -28558,7 +29240,8 @@ fn coerceAnonStructToStructPtrs(
2855829240 ptr_anon_struct: Air.Inst.Ref,
2855929241 anon_struct_src: LazySrcLoc,
2856029242) !Air.Inst.Ref {
28561 const struct_ty = ptr_struct_ty.childType();
29243 const mod = sema.mod;
29244 const struct_ty = ptr_struct_ty.childType(mod);
2856229245 const anon_struct = try sema.analyzeLoad(block, anon_struct_src, ptr_anon_struct, anon_struct_src);
2856329246 const struct_inst = try sema.coerceTupleToStruct(block, struct_ty, anon_struct, anon_struct_src);
2856429247 return sema.analyzeRef(block, struct_ty_src, struct_inst);
......@@ -28573,15 +29256,16 @@ fn coerceArrayLike(
2857329256 inst: Air.Inst.Ref,
2857429257 inst_src: LazySrcLoc,
2857529258) !Air.Inst.Ref {
29259 const mod = sema.mod;
2857629260 const inst_ty = sema.typeOf(inst);
28577 const inst_len = inst_ty.arrayLen();
28578 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen());
28579 const target = sema.mod.getTarget();
29261 const inst_len = inst_ty.arrayLen(mod);
29262 const dest_len = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLen(mod));
29263 const target = mod.getTarget();
2858029264
2858129265 if (dest_len != inst_len) {
2858229266 const msg = msg: {
2858329267 const msg = try sema.errMsg(block, inst_src, "expected type '{}', found '{}'", .{
28584 dest_ty.fmt(sema.mod), inst_ty.fmt(sema.mod),
29268 dest_ty.fmt(mod), inst_ty.fmt(mod),
2858529269 });
2858629270 errdefer msg.destroy(sema.gpa);
2858729271 try sema.errNote(block, dest_ty_src, msg, "destination has length {d}", .{dest_len});
......@@ -28591,35 +29275,32 @@ fn coerceArrayLike(
2859129275 return sema.failWithOwnedErrorMsg(msg);
2859229276 }
2859329277
28594 const dest_elem_ty = dest_ty.childType();
28595 const inst_elem_ty = inst_ty.childType();
29278 const dest_elem_ty = dest_ty.childType(mod);
29279 const inst_elem_ty = inst_ty.childType(mod);
2859629280 const in_memory_result = try sema.coerceInMemoryAllowed(block, dest_elem_ty, inst_elem_ty, false, target, dest_ty_src, inst_src);
2859729281 if (in_memory_result == .ok) {
2859829282 if (try sema.resolveMaybeUndefVal(inst)) |inst_val| {
2859929283 // These types share the same comptime value representation.
28600 return sema.addConstant(dest_ty, inst_val);
29284 return sema.coerceInMemory(block, inst_val, inst_ty, dest_ty, dest_ty_src);
2860129285 }
2860229286 try sema.requireRuntimeBlock(block, inst_src, null);
2860329287 return block.addBitCast(dest_ty, inst);
2860429288 }
2860529289
28606 const element_vals = try sema.arena.alloc(Value, dest_len);
29290 const element_vals = try sema.arena.alloc(InternPool.Index, dest_len);
2860729291 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_len);
2860829292 var runtime_src: ?LazySrcLoc = null;
2860929293
28610 for (element_vals, 0..) |*elem, i| {
28611 const index_ref = try sema.addConstant(
28612 Type.usize,
28613 try Value.Tag.int_u64.create(sema.arena, i),
28614 );
29294 for (element_vals, element_refs, 0..) |*val, *ref, i| {
29295 const index_ref = try sema.addConstant(Type.usize, try mod.intValue(Type.usize, i));
2861529296 const src = inst_src; // TODO better source location
2861629297 const elem_src = inst_src; // TODO better source location
2861729298 const elem_ref = try sema.elemValArray(block, src, inst_src, inst, elem_src, index_ref, true);
2861829299 const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src);
28619 element_refs[i] = coerced;
29300 ref.* = coerced;
2862029301 if (runtime_src == null) {
2862129302 if (try sema.resolveMaybeUndefVal(coerced)) |elem_val| {
28622 elem.* = elem_val;
29303 val.* = try elem_val.intern(dest_elem_ty, mod);
2862329304 } else {
2862429305 runtime_src = elem_src;
2862529306 }
......@@ -28631,10 +29312,10 @@ fn coerceArrayLike(
2863129312 return block.addAggregateInit(dest_ty, element_refs);
2863229313 }
2863329314
28634 return sema.addConstant(
28635 dest_ty,
28636 try Value.Tag.aggregate.create(sema.arena, element_vals),
28637 );
29315 return sema.addConstant(dest_ty, (try mod.intern(.{ .aggregate = .{
29316 .ty = dest_ty.toIntern(),
29317 .storage = .{ .elems = element_vals },
29318 } })).toValue());
2863829319}
2863929320
2864029321/// If the lengths match, coerces element-wise.
......@@ -28646,9 +29327,10 @@ fn coerceTupleToArray(
2864629327 inst: Air.Inst.Ref,
2864729328 inst_src: LazySrcLoc,
2864829329) !Air.Inst.Ref {
29330 const mod = sema.mod;
2864929331 const inst_ty = sema.typeOf(inst);
28650 const inst_len = inst_ty.arrayLen();
28651 const dest_len = dest_ty.arrayLen();
29332 const inst_len = inst_ty.arrayLen(mod);
29333 const dest_len = dest_ty.arrayLen(mod);
2865229334
2865329335 if (dest_len != inst_len) {
2865429336 const msg = msg: {
......@@ -28663,26 +29345,27 @@ fn coerceTupleToArray(
2866329345 return sema.failWithOwnedErrorMsg(msg);
2866429346 }
2866529347
28666 const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_ty.arrayLenIncludingSentinel());
28667 const element_vals = try sema.arena.alloc(Value, dest_elems);
29348 const dest_elems = try sema.usizeCast(block, dest_ty_src, dest_len);
29349 const element_vals = try sema.arena.alloc(InternPool.Index, dest_elems);
2866829350 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_elems);
28669 const dest_elem_ty = dest_ty.childType();
29351 const dest_elem_ty = dest_ty.childType(mod);
2867029352
2867129353 var runtime_src: ?LazySrcLoc = null;
28672 for (element_vals, 0..) |*elem, i_usize| {
29354 for (element_vals, element_refs, 0..) |*val, *ref, i_usize| {
2867329355 const i = @intCast(u32, i_usize);
2867429356 if (i_usize == inst_len) {
28675 elem.* = dest_ty.sentinel().?;
28676 element_refs[i] = try sema.addConstant(dest_elem_ty, elem.*);
29357 const sentinel_val = dest_ty.sentinel(mod).?;
29358 val.* = sentinel_val.toIntern();
29359 ref.* = try sema.addConstant(dest_elem_ty, sentinel_val);
2867729360 break;
2867829361 }
2867929362 const elem_src = inst_src; // TODO better source location
2868029363 const elem_ref = try sema.tupleField(block, inst_src, inst, elem_src, i);
2868129364 const coerced = try sema.coerce(block, dest_elem_ty, elem_ref, elem_src);
28682 element_refs[i] = coerced;
29365 ref.* = coerced;
2868329366 if (runtime_src == null) {
2868429367 if (try sema.resolveMaybeUndefVal(coerced)) |elem_val| {
28685 elem.* = elem_val;
29368 val.* = try elem_val.intern(dest_elem_ty, mod);
2868629369 } else {
2868729370 runtime_src = elem_src;
2868829371 }
......@@ -28694,10 +29377,10 @@ fn coerceTupleToArray(
2869429377 return block.addAggregateInit(dest_ty, element_refs);
2869529378 }
2869629379
28697 return sema.addConstant(
28698 dest_ty,
28699 try Value.Tag.aggregate.create(sema.arena, element_vals),
28700 );
29380 return sema.addConstant(dest_ty, (try mod.intern(.{ .aggregate = .{
29381 .ty = dest_ty.toIntern(),
29382 .storage = .{ .elems = element_vals },
29383 } })).toValue());
2870129384}
2870229385
2870329386/// If the lengths match, coerces element-wise.
......@@ -28709,10 +29392,11 @@ fn coerceTupleToSlicePtrs(
2870929392 ptr_tuple: Air.Inst.Ref,
2871029393 tuple_src: LazySrcLoc,
2871129394) !Air.Inst.Ref {
28712 const tuple_ty = sema.typeOf(ptr_tuple).childType();
29395 const mod = sema.mod;
29396 const tuple_ty = sema.typeOf(ptr_tuple).childType(mod);
2871329397 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);
28714 const slice_info = slice_ty.ptrInfo().data;
28715 const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(), slice_info.sentinel, slice_info.pointee_type, sema.mod);
29398 const slice_info = slice_ty.ptrInfo(mod);
29399 const array_ty = try Type.array(sema.arena, tuple_ty.structFieldCount(mod), slice_info.sentinel, slice_info.pointee_type, sema.mod);
2871629400 const array_inst = try sema.coerceTupleToArray(block, array_ty, slice_ty_src, tuple, tuple_src);
2871729401 if (slice_info.@"align" != 0) {
2871829402 return sema.fail(block, slice_ty_src, "TODO: override the alignment of the array decl we create here", .{});
......@@ -28730,8 +29414,9 @@ fn coerceTupleToArrayPtrs(
2873029414 ptr_tuple: Air.Inst.Ref,
2873129415 tuple_src: LazySrcLoc,
2873229416) !Air.Inst.Ref {
29417 const mod = sema.mod;
2873329418 const tuple = try sema.analyzeLoad(block, tuple_src, ptr_tuple, tuple_src);
28734 const ptr_info = ptr_array_ty.ptrInfo().data;
29419 const ptr_info = ptr_array_ty.ptrInfo(mod);
2873529420 const array_ty = ptr_info.pointee_type;
2873629421 const array_inst = try sema.coerceTupleToArray(block, array_ty, array_ty_src, tuple, tuple_src);
2873729422 if (ptr_info.@"align" != 0) {
......@@ -28750,27 +29435,41 @@ fn coerceTupleToStruct(
2875029435 inst: Air.Inst.Ref,
2875129436 inst_src: LazySrcLoc,
2875229437) !Air.Inst.Ref {
29438 const mod = sema.mod;
29439 const ip = &mod.intern_pool;
2875329440 const struct_ty = try sema.resolveTypeFields(dest_ty);
2875429441
28755 if (struct_ty.isTupleOrAnonStruct()) {
29442 if (struct_ty.isTupleOrAnonStruct(mod)) {
2875629443 return sema.coerceTupleToTuple(block, struct_ty, inst, inst_src);
2875729444 }
2875829445
28759 const fields = struct_ty.structFields();
28760 const field_vals = try sema.arena.alloc(Value, fields.count());
29446 const fields = struct_ty.structFields(mod);
29447 const field_vals = try sema.arena.alloc(InternPool.Index, fields.count());
2876129448 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
2876229449 @memset(field_refs, .none);
2876329450
2876429451 const inst_ty = sema.typeOf(inst);
2876529452 var runtime_src: ?LazySrcLoc = null;
28766 const field_count = inst_ty.structFieldCount();
28767 var field_i: u32 = 0;
28768 while (field_i < field_count) : (field_i += 1) {
28769 const field_src = inst_src; // TODO better source location
28770 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|
28771 payload.data.names[field_i]
29453 const field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
29454 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
29455 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
29456 struct_obj.fields.count()
2877229457 else
28773 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
29458 0,
29459 else => unreachable,
29460 };
29461 for (0..field_count) |field_index_usize| {
29462 const field_i = @intCast(u32, field_index_usize);
29463 const field_src = inst_src; // TODO better source location
29464 // https://github.com/ziglang/zig/issues/15709
29465 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
29466 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
29467 anon_struct_type.names[field_i]
29468 else
29469 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
29470 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
29471 else => unreachable,
29472 };
2877429473 const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
2877529474 const field = fields.values()[field_index];
2877629475 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
......@@ -28781,13 +29480,13 @@ fn coerceTupleToStruct(
2878129480 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
2878229481 };
2878329482
28784 if (!init_val.eql(field.default_val, field.ty, sema.mod)) {
29483 if (!init_val.eql(field.default_val.toValue(), field.ty, sema.mod)) {
2878529484 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
2878629485 }
2878729486 }
2878829487 if (runtime_src == null) {
2878929488 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {
28790 field_vals[field_index] = field_val;
29489 field_vals[field_index] = field_val.toIntern();
2879129490 } else {
2879229491 runtime_src = field_src;
2879329492 }
......@@ -28804,9 +29503,9 @@ fn coerceTupleToStruct(
2880429503 const field_name = fields.keys()[i];
2880529504 const field = fields.values()[i];
2880629505 const field_src = inst_src; // TODO better source location
28807 if (field.default_val.tag() == .unreachable_value) {
28808 const template = "missing struct field: {s}";
28809 const args = .{field_name};
29506 if (field.default_val == .none) {
29507 const template = "missing struct field: {}";
29508 const args = .{field_name.fmt(ip)};
2881029509 if (root_msg) |msg| {
2881129510 try sema.errNote(block, field_src, msg, template, args);
2881229511 } else {
......@@ -28817,7 +29516,7 @@ fn coerceTupleToStruct(
2881729516 if (runtime_src == null) {
2881829517 field_vals[i] = field.default_val;
2881929518 } else {
28820 field_ref.* = try sema.addConstant(field.ty, field.default_val);
29519 field_ref.* = try sema.addConstant(field.ty, field.default_val.toValue());
2882129520 }
2882229521 }
2882329522
......@@ -28832,10 +29531,14 @@ fn coerceTupleToStruct(
2883229531 return block.addAggregateInit(struct_ty, field_refs);
2883329532 }
2883429533
28835 return sema.addConstant(
28836 struct_ty,
28837 try Value.Tag.aggregate.create(sema.arena, field_vals),
28838 );
29534 const struct_val = try mod.intern(.{ .aggregate = .{
29535 .ty = struct_ty.toIntern(),
29536 .storage = .{ .elems = field_vals },
29537 } });
29538 // TODO: figure out InternPool removals for incremental compilation
29539 //errdefer ip.remove(struct_val);
29540
29541 return sema.addConstant(struct_ty, struct_val.toValue());
2883929542}
2884029543
2884129544fn coerceTupleToTuple(
......@@ -28845,47 +29548,76 @@ fn coerceTupleToTuple(
2884529548 inst: Air.Inst.Ref,
2884629549 inst_src: LazySrcLoc,
2884729550) !Air.Inst.Ref {
28848 const dest_field_count = tuple_ty.structFieldCount();
28849 const field_vals = try sema.arena.alloc(Value, dest_field_count);
29551 const mod = sema.mod;
29552 const ip = &mod.intern_pool;
29553 const dest_field_count = switch (ip.indexToKey(tuple_ty.toIntern())) {
29554 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
29555 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
29556 struct_obj.fields.count()
29557 else
29558 0,
29559 else => unreachable,
29560 };
29561 const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);
2885029562 const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
2885129563 @memset(field_refs, .none);
2885229564
2885329565 const inst_ty = sema.typeOf(inst);
28854 const inst_field_count = inst_ty.structFieldCount();
28855 if (inst_field_count > dest_field_count) return error.NotCoercible;
29566 const src_field_count = switch (ip.indexToKey(inst_ty.toIntern())) {
29567 .anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
29568 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
29569 struct_obj.fields.count()
29570 else
29571 0,
29572 else => unreachable,
29573 };
29574 if (src_field_count > dest_field_count) return error.NotCoercible;
2885629575
2885729576 var runtime_src: ?LazySrcLoc = null;
28858 var field_i: u32 = 0;
28859 while (field_i < inst_field_count) : (field_i += 1) {
29577 for (0..dest_field_count) |field_index_usize| {
29578 const field_i = @intCast(u32, field_index_usize);
2886029579 const field_src = inst_src; // TODO better source location
28861 const field_name = if (inst_ty.castTag(.anon_struct)) |payload|
28862 payload.data.names[field_i]
28863 else
28864 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
29580 // https://github.com/ziglang/zig/issues/15709
29581 const field_name: InternPool.NullTerminatedString = switch (ip.indexToKey(inst_ty.toIntern())) {
29582 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
29583 anon_struct_type.names[field_i]
29584 else
29585 try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}),
29586 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
29587 else => unreachable,
29588 };
2886529589
28866 if (mem.eql(u8, field_name, "len")) {
29590 if (ip.stringEqlSlice(field_name, "len"))
2886729591 return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
28868 }
29592
29593 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
29594 .anon_struct_type => |anon_struct_type| anon_struct_type.types[field_index_usize].toType(),
29595 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].ty,
29596 else => unreachable,
29597 };
29598 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
29599 .anon_struct_type => |anon_struct_type| anon_struct_type.values[field_index_usize],
29600 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].default_val,
29601 else => unreachable,
29602 };
2886929603
2887029604 const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
2887129605
28872 const field_ty = tuple_ty.structFieldType(field_i);
28873 const default_val = tuple_ty.structFieldDefaultValue(field_i);
2887429606 const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
2887529607 const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
2887629608 field_refs[field_index] = coerced;
28877 if (default_val.tag() != .unreachable_value) {
29609 if (default_val != .none) {
2887829610 const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
2887929611 return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
2888029612 };
2888129613
28882 if (!init_val.eql(default_val, field_ty, sema.mod)) {
29614 if (!init_val.eql(default_val.toValue(), field_ty, sema.mod)) {
2888329615 return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
2888429616 }
2888529617 }
2888629618 if (runtime_src == null) {
2888729619 if (try sema.resolveMaybeUndefVal(coerced)) |field_val| {
28888 field_vals[field_index] = field_val;
29620 field_vals[field_index] = field_val.toIntern();
2888929621 } else {
2889029622 runtime_src = field_src;
2889129623 }
......@@ -28899,12 +29631,15 @@ fn coerceTupleToTuple(
2889929631 for (field_refs, 0..) |*field_ref, i| {
2890029632 if (field_ref.* != .none) continue;
2890129633
28902 const default_val = tuple_ty.structFieldDefaultValue(i);
28903 const field_ty = tuple_ty.structFieldType(i);
29634 const default_val = switch (ip.indexToKey(tuple_ty.toIntern())) {
29635 .anon_struct_type => |anon_struct_type| anon_struct_type.values[i],
29636 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].default_val,
29637 else => unreachable,
29638 };
2890429639
2890529640 const field_src = inst_src; // TODO better source location
28906 if (default_val.tag() == .unreachable_value) {
28907 if (tuple_ty.isTuple()) {
29641 if (default_val == .none) {
29642 if (tuple_ty.isTuple(mod)) {
2890829643 const template = "missing tuple field: {d}";
2890929644 if (root_msg) |msg| {
2891029645 try sema.errNote(block, field_src, msg, template, .{i});
......@@ -28913,8 +29648,8 @@ fn coerceTupleToTuple(
2891329648 }
2891429649 continue;
2891529650 }
28916 const template = "missing struct field: {s}";
28917 const args = .{tuple_ty.structFieldName(i)};
29651 const template = "missing struct field: {}";
29652 const args = .{tuple_ty.structFieldName(i, mod).fmt(ip)};
2891829653 if (root_msg) |msg| {
2891929654 try sema.errNote(block, field_src, msg, template, args);
2892029655 } else {
......@@ -28925,7 +29660,12 @@ fn coerceTupleToTuple(
2892529660 if (runtime_src == null) {
2892629661 field_vals[i] = default_val;
2892729662 } else {
28928 field_ref.* = try sema.addConstant(field_ty, default_val);
29663 const field_ty = switch (ip.indexToKey(tuple_ty.toIntern())) {
29664 .anon_struct_type => |anon_struct_type| anon_struct_type.types[i].toType(),
29665 .struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].ty,
29666 else => unreachable,
29667 };
29668 field_ref.* = try sema.addConstant(field_ty, default_val.toValue());
2892929669 }
2893029670 }
2893129671
......@@ -28942,7 +29682,10 @@ fn coerceTupleToTuple(
2894229682
2894329683 return sema.addConstant(
2894429684 tuple_ty,
28945 try Value.Tag.aggregate.create(sema.arena, field_vals),
29685 (try mod.intern(.{ .aggregate = .{
29686 .ty = tuple_ty.toIntern(),
29687 .storage = .{ .elems = field_vals },
29688 } })).toValue(),
2894629689 );
2894729690}
2894829691
......@@ -28959,7 +29702,7 @@ fn analyzeDeclVal(
2895929702 const decl_ref = try sema.analyzeDeclRefInner(decl_index, false);
2896029703 const result = try sema.analyzeLoad(block, src, decl_ref, src);
2896129704 if (Air.refToIndex(result)) |index| {
28962 if (sema.air_instructions.items(.tag)[index] == .constant and !block.is_typeof) {
29705 if (sema.air_instructions.items(.tag)[index] == .interned and !block.is_typeof) {
2896329706 try sema.decl_val_table.put(sema.gpa, decl_index, result);
2896429707 }
2896529708 }
......@@ -28980,13 +29723,14 @@ fn addReferencedBy(
2898029723}
2898129724
2898229725fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
28983 const decl = sema.mod.declPtr(decl_index);
29726 const mod = sema.mod;
29727 const decl = mod.declPtr(decl_index);
2898429728 if (decl.analysis == .in_progress) {
28985 const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(), "dependency loop detected", .{});
29729 const msg = try Module.ErrorMsg.create(sema.gpa, decl.srcLoc(mod), "dependency loop detected", .{});
2898629730 return sema.failWithOwnedErrorMsg(msg);
2898729731 }
2898829732
28989 sema.mod.ensureDeclAnalyzed(decl_index) catch |err| {
29733 mod.ensureDeclAnalyzed(decl_index) catch |err| {
2899029734 if (sema.owner_func) |owner_func| {
2899129735 owner_func.state = .dependency_failure;
2899229736 } else {
......@@ -28996,7 +29740,7 @@ fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
2899629740 };
2899729741}
2899829742
28999fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
29743fn ensureFuncBodyAnalyzed(sema: *Sema, func: Module.Fn.Index) CompileError!void {
2900029744 sema.mod.ensureFuncBodyAnalyzed(func) catch |err| {
2900129745 if (sema.owner_func) |owner_func| {
2900229746 owner_func.state = .dependency_failure;
......@@ -29008,23 +29752,33 @@ fn ensureFuncBodyAnalyzed(sema: *Sema, func: *Module.Fn) CompileError!void {
2900829752}
2900929753
2901029754fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value {
29755 const mod = sema.mod;
2901129756 var anon_decl = try block.startAnonDecl();
2901229757 defer anon_decl.deinit();
2901329758 const decl = try anon_decl.finish(
29014 try ty.copy(anon_decl.arena()),
29015 try val.copy(anon_decl.arena()),
29759 ty,
29760 val,
2901629761 0, // default alignment
2901729762 );
2901829763 try sema.maybeQueueFuncBodyAnalysis(decl);
29019 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl);
29020 return try Value.Tag.decl_ref.create(sema.arena, decl);
29764 try mod.declareDeclDependency(sema.owner_decl_index, decl);
29765 const result = try mod.intern(.{ .ptr = .{
29766 .ty = (try mod.singleConstPtrType(ty)).toIntern(),
29767 .addr = .{ .decl = decl },
29768 } });
29769 return result.toValue();
2902129770}
2902229771
2902329772fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value {
29024 const val = opt_val orelse return Value.null;
29025 const ptr_val = try sema.refValue(block, ty, val);
29026 const result = try Value.Tag.opt_payload.create(sema.arena, ptr_val);
29027 return result;
29773 const mod = sema.mod;
29774 const ptr_anyopaque_ty = try mod.singleConstPtrType(Type.anyopaque);
29775 return (try mod.intern(.{ .opt = .{
29776 .ty = (try mod.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(),
29777 .val = if (opt_val) |val| (try mod.getCoerced(
29778 try sema.refValue(block, ty, val),
29779 ptr_anyopaque_ty,
29780 )).toIntern() else .none,
29781 } })).toValue();
2902829782}
2902929783
2903029784fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref {
......@@ -29036,42 +29790,37 @@ fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref
2903629790/// decl_ref to end up in runtime code, the function body must be analyzed: `analyzeDeclRef` wraps
2903729791/// this function with `analyze_fn_body` set to true.
2903829792fn analyzeDeclRefInner(sema: *Sema, decl_index: Decl.Index, analyze_fn_body: bool) CompileError!Air.Inst.Ref {
29039 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
29793 const mod = sema.mod;
29794 try mod.declareDeclDependency(sema.owner_decl_index, decl_index);
2904029795 try sema.ensureDeclAnalyzed(decl_index);
2904129796
29042 const decl = sema.mod.declPtr(decl_index);
29797 const decl = mod.declPtr(decl_index);
2904329798 const decl_tv = try decl.typedValue();
29044 if (decl_tv.val.castTag(.variable)) |payload| {
29045 const variable = payload.data;
29046 const ty = try Type.ptr(sema.arena, sema.mod, .{
29047 .pointee_type = decl_tv.ty,
29048 .mutable = variable.is_mutable,
29049 .@"addrspace" = decl.@"addrspace",
29050 .@"align" = decl.@"align",
29051 });
29052 return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl_index));
29053 }
29799 const ptr_ty = try mod.ptrType(.{
29800 .child = decl_tv.ty.toIntern(),
29801 .flags = .{
29802 .alignment = InternPool.Alignment.fromByteUnits(decl.@"align"),
29803 .is_const = if (decl.val.getVariable(mod)) |variable| variable.is_const else true,
29804 .address_space = decl.@"addrspace",
29805 },
29806 });
2905429807 if (analyze_fn_body) {
2905529808 try sema.maybeQueueFuncBodyAnalysis(decl_index);
2905629809 }
29057 return sema.addConstant(
29058 try Type.ptr(sema.arena, sema.mod, .{
29059 .pointee_type = decl_tv.ty,
29060 .mutable = false,
29061 .@"addrspace" = decl.@"addrspace",
29062 .@"align" = decl.@"align",
29063 }),
29064 try Value.Tag.decl_ref.create(sema.arena, decl_index),
29065 );
29810 return sema.addConstant(ptr_ty, (try mod.intern(.{ .ptr = .{
29811 .ty = ptr_ty.toIntern(),
29812 .addr = .{ .decl = decl_index },
29813 } })).toValue());
2906629814}
2906729815
2906829816fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: Decl.Index) !void {
29069 const decl = sema.mod.declPtr(decl_index);
29817 const mod = sema.mod;
29818 const decl = mod.declPtr(decl_index);
2907029819 const tv = try decl.typedValue();
29071 if (tv.ty.zigTypeTag() != .Fn) return;
29820 if (tv.ty.zigTypeTag(mod) != .Fn) return;
2907229821 if (!try sema.fnHasRuntimeBits(tv.ty)) return;
29073 const func = tv.val.castTag(.function) orelse return; // undef or extern_fn
29074 try sema.mod.ensureFuncBodyAnalysisQueued(func.data);
29822 const func_index = mod.intern_pool.indexToFunc(tv.val.toIntern()).unwrap() orelse return; // undef or extern_fn
29823 try mod.ensureFuncBodyAnalysisQueued(func_index);
2907529824}
2907629825
2907729826fn analyzeRef(
......@@ -29083,18 +29832,16 @@ fn analyzeRef(
2908329832 const operand_ty = sema.typeOf(operand);
2908429833
2908529834 if (try sema.resolveMaybeUndefVal(operand)) |val| {
29086 switch (val.tag()) {
29087 .extern_fn, .function => {
29088 const decl_index = val.pointerDecl().?;
29089 return sema.analyzeDeclRef(decl_index);
29090 },
29835 switch (sema.mod.intern_pool.indexToKey(val.toIntern())) {
29836 .extern_func => |extern_func| return sema.analyzeDeclRef(extern_func.decl),
29837 .func => |func| return sema.analyzeDeclRef(sema.mod.funcPtr(func.index).owner_decl),
2909129838 else => {},
2909229839 }
2909329840 var anon_decl = try block.startAnonDecl();
2909429841 defer anon_decl.deinit();
2909529842 return sema.analyzeDeclRef(try anon_decl.finish(
29096 try operand_ty.copy(anon_decl.arena()),
29097 try val.copy(anon_decl.arena()),
29843 operand_ty,
29844 val,
2909829845 0, // default alignment
2909929846 ));
2910029847 }
......@@ -29124,9 +29871,10 @@ fn analyzeLoad(
2912429871 ptr: Air.Inst.Ref,
2912529872 ptr_src: LazySrcLoc,
2912629873) CompileError!Air.Inst.Ref {
29874 const mod = sema.mod;
2912729875 const ptr_ty = sema.typeOf(ptr);
29128 const elem_ty = switch (ptr_ty.zigTypeTag()) {
29129 .Pointer => ptr_ty.childType(),
29876 const elem_ty = switch (ptr_ty.zigTypeTag(mod)) {
29877 .Pointer => ptr_ty.childType(mod),
2913029878 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)}),
2913129879 };
2913229880
......@@ -29136,11 +29884,11 @@ fn analyzeLoad(
2913629884
2913729885 if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| {
2913829886 if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| {
29139 return sema.addConstant(elem_ty, elem_val);
29887 return sema.addConstant(elem_ty, try mod.getCoerced(elem_val, elem_ty));
2914029888 }
2914129889 }
2914229890
29143 if (ptr_ty.ptrInfo().data.vector_index == .runtime) {
29891 if (ptr_ty.ptrInfo(mod).vector_index == .runtime) {
2914429892 const ptr_inst = Air.refToIndex(ptr).?;
2914529893 const air_tags = sema.air_instructions.items(.tag);
2914629894 if (air_tags[ptr_inst] == .ptr_elem_ptr) {
......@@ -29163,11 +29911,11 @@ fn analyzeSlicePtr(
2916329911 slice: Air.Inst.Ref,
2916429912 slice_ty: Type,
2916529913) CompileError!Air.Inst.Ref {
29166 const buf = try sema.arena.create(Type.SlicePtrFieldTypeBuffer);
29167 const result_ty = slice_ty.slicePtrFieldType(buf);
29914 const mod = sema.mod;
29915 const result_ty = slice_ty.slicePtrFieldType(mod);
2916829916 if (try sema.resolveMaybeUndefVal(slice)) |val| {
29169 if (val.isUndef()) return sema.addConstUndef(result_ty);
29170 return sema.addConstant(result_ty, val.slicePtr());
29917 if (val.isUndef(mod)) return sema.addConstUndef(result_ty);
29918 return sema.addConstant(result_ty, val.slicePtr(mod));
2917129919 }
2917229920 try sema.requireRuntimeBlock(block, slice_src, null);
2917329921 return block.addTyOp(.slice_ptr, result_ty, slice);
......@@ -29179,8 +29927,9 @@ fn analyzeSliceLen(
2917929927 src: LazySrcLoc,
2918029928 slice_inst: Air.Inst.Ref,
2918129929) CompileError!Air.Inst.Ref {
29930 const mod = sema.mod;
2918229931 if (try sema.resolveMaybeUndefVal(slice_inst)) |slice_val| {
29183 if (slice_val.isUndef()) {
29932 if (slice_val.isUndef(mod)) {
2918429933 return sema.addConstUndef(Type.usize);
2918529934 }
2918629935 return sema.addIntUnsigned(Type.usize, slice_val.sliceLen(sema.mod));
......@@ -29196,12 +29945,13 @@ fn analyzeIsNull(
2919629945 operand: Air.Inst.Ref,
2919729946 invert_logic: bool,
2919829947) CompileError!Air.Inst.Ref {
29948 const mod = sema.mod;
2919929949 const result_ty = Type.bool;
2920029950 if (try sema.resolveMaybeUndefVal(operand)) |opt_val| {
29201 if (opt_val.isUndef()) {
29951 if (opt_val.isUndef(mod)) {
2920229952 return sema.addConstUndef(result_ty);
2920329953 }
29204 const is_null = opt_val.isNull();
29954 const is_null = opt_val.isNull(mod);
2920529955 const bool_value = if (invert_logic) !is_null else is_null;
2920629956 if (bool_value) {
2920729957 return Air.Inst.Ref.bool_true;
......@@ -29212,11 +29962,10 @@ fn analyzeIsNull(
2921229962
2921329963 const inverted_non_null_res = if (invert_logic) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
2921429964 const operand_ty = sema.typeOf(operand);
29215 var buf: Type.Payload.ElemType = undefined;
29216 if (operand_ty.zigTypeTag() == .Optional and operand_ty.optionalChild(&buf).zigTypeTag() == .NoReturn) {
29965 if (operand_ty.zigTypeTag(mod) == .Optional and operand_ty.optionalChild(mod).zigTypeTag(mod) == .NoReturn) {
2921729966 return inverted_non_null_res;
2921829967 }
29219 if (operand_ty.zigTypeTag() != .Optional and !operand_ty.isPtrLikeOptional()) {
29968 if (operand_ty.zigTypeTag(mod) != .Optional and !operand_ty.isPtrLikeOptional(mod)) {
2922029969 return inverted_non_null_res;
2922129970 }
2922229971 try sema.requireRuntimeBlock(block, src, null);
......@@ -29230,11 +29979,12 @@ fn analyzePtrIsNonErrComptimeOnly(
2923029979 src: LazySrcLoc,
2923129980 operand: Air.Inst.Ref,
2923229981) CompileError!Air.Inst.Ref {
29982 const mod = sema.mod;
2923329983 const ptr_ty = sema.typeOf(operand);
29234 assert(ptr_ty.zigTypeTag() == .Pointer);
29235 const child_ty = ptr_ty.childType();
29984 assert(ptr_ty.zigTypeTag(mod) == .Pointer);
29985 const child_ty = ptr_ty.childType(mod);
2923629986
29237 const child_tag = child_ty.zigTypeTag();
29987 const child_tag = child_ty.zigTypeTag(mod);
2923829988 if (child_tag != .ErrorSet and child_tag != .ErrorUnion) return Air.Inst.Ref.bool_true;
2923929989 if (child_tag == .ErrorSet) return Air.Inst.Ref.bool_false;
2924029990 assert(child_tag == .ErrorUnion);
......@@ -29251,14 +30001,15 @@ fn analyzeIsNonErrComptimeOnly(
2925130001 src: LazySrcLoc,
2925230002 operand: Air.Inst.Ref,
2925330003) CompileError!Air.Inst.Ref {
30004 const mod = sema.mod;
2925430005 const operand_ty = sema.typeOf(operand);
29255 const ot = operand_ty.zigTypeTag();
30006 const ot = operand_ty.zigTypeTag(mod);
2925630007 if (ot != .ErrorSet and ot != .ErrorUnion) return Air.Inst.Ref.bool_true;
2925730008 if (ot == .ErrorSet) return Air.Inst.Ref.bool_false;
2925830009 assert(ot == .ErrorUnion);
2925930010
29260 const payload_ty = operand_ty.errorUnionPayload();
29261 if (payload_ty.zigTypeTag() == .NoReturn) {
30011 const payload_ty = operand_ty.errorUnionPayload(mod);
30012 if (payload_ty.zigTypeTag(mod) == .NoReturn) {
2926230013 return Air.Inst.Ref.bool_false;
2926330014 }
2926430015
......@@ -29279,50 +30030,56 @@ fn analyzeIsNonErrComptimeOnly(
2927930030
2928030031 // exception if the error union error set is known to be empty,
2928130032 // we allow the comparison but always make it comptime-known.
29282 const set_ty = operand_ty.errorUnionSet();
29283 switch (set_ty.tag()) {
29284 .anyerror => {},
29285 .error_set_inferred => blk: {
29286 // If the error set is empty, we must return a comptime true or false.
29287 // However we want to avoid unnecessarily resolving an inferred error set
29288 // in case it is already non-empty.
29289 const ies = set_ty.castTag(.error_set_inferred).?.data;
29290 if (ies.is_anyerror) break :blk;
29291 if (ies.errors.count() != 0) break :blk;
29292 if (maybe_operand_val == null) {
29293 // Try to avoid resolving inferred error set if possible.
29294 if (ies.errors.count() != 0) break :blk;
30033 const set_ty = operand_ty.errorUnionSet(mod);
30034 switch (set_ty.toIntern()) {
30035 .anyerror_type => {},
30036 else => switch (mod.intern_pool.indexToKey(set_ty.toIntern())) {
30037 .error_set_type => |error_set_type| {
30038 if (error_set_type.names.len == 0) return Air.Inst.Ref.bool_true;
30039 },
30040 .inferred_error_set_type => |ies_index| blk: {
30041 // If the error set is empty, we must return a comptime true or false.
30042 // However we want to avoid unnecessarily resolving an inferred error set
30043 // in case it is already non-empty.
30044 const ies = mod.inferredErrorSetPtr(ies_index);
2929530045 if (ies.is_anyerror) break :blk;
29296 for (ies.inferred_error_sets.keys()) |other_ies| {
29297 if (ies == other_ies) continue;
29298 try sema.resolveInferredErrorSet(block, src, other_ies);
29299 if (other_ies.is_anyerror) {
29300 ies.is_anyerror = true;
29301 ies.is_resolved = true;
29302 break :blk;
29303 }
30046 if (ies.errors.count() != 0) break :blk;
30047 if (maybe_operand_val == null) {
30048 // Try to avoid resolving inferred error set if possible.
30049 if (ies.errors.count() != 0) break :blk;
30050 if (ies.is_anyerror) break :blk;
30051 for (ies.inferred_error_sets.keys()) |other_ies_index| {
30052 if (ies_index == other_ies_index) continue;
30053 try sema.resolveInferredErrorSet(block, src, other_ies_index);
30054 const other_ies = mod.inferredErrorSetPtr(other_ies_index);
30055 if (other_ies.is_anyerror) {
30056 ies.is_anyerror = true;
30057 ies.is_resolved = true;
30058 break :blk;
30059 }
2930430060
29305 if (other_ies.errors.count() != 0) break :blk;
29306 }
29307 if (ies.func == sema.owner_func) {
29308 // We're checking the inferred errorset of the current function and none of
29309 // its child inferred error sets contained any errors meaning that any value
29310 // so far with this type can't contain errors either.
29311 return Air.Inst.Ref.bool_true;
30061 if (other_ies.errors.count() != 0) break :blk;
30062 }
30063 if (ies.func == sema.owner_func_index.unwrap()) {
30064 // We're checking the inferred errorset of the current function and none of
30065 // its child inferred error sets contained any errors meaning that any value
30066 // so far with this type can't contain errors either.
30067 return Air.Inst.Ref.bool_true;
30068 }
30069 try sema.resolveInferredErrorSet(block, src, ies_index);
30070 if (ies.is_anyerror) break :blk;
30071 if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
2931230072 }
29313 try sema.resolveInferredErrorSet(block, src, ies);
29314 if (ies.is_anyerror) break :blk;
29315 if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true;
29316 }
30073 },
30074 else => unreachable,
2931730075 },
29318 else => if (set_ty.errorSetNames().len == 0) return Air.Inst.Ref.bool_true,
2931930076 }
2932030077
2932130078 if (maybe_operand_val) |err_union| {
29322 if (err_union.isUndef()) {
30079 if (err_union.isUndef(mod)) {
2932330080 return sema.addConstUndef(Type.bool);
2932430081 }
29325 if (err_union.getError() == null) {
30082 if (err_union.getErrorName(mod) == .none) {
2932630083 return Air.Inst.Ref.bool_true;
2932730084 } else {
2932830085 return Air.Inst.Ref.bool_false;
......@@ -29375,72 +30132,78 @@ fn analyzeSlice(
2937530132 end_src: LazySrcLoc,
2937630133 by_length: bool,
2937730134) CompileError!Air.Inst.Ref {
30135 const mod = sema.mod;
2937830136 // Slice expressions can operate on a variable whose type is an array. This requires
2937930137 // the slice operand to be a pointer. In the case of a non-array, it will be a double pointer.
2938030138 const ptr_ptr_ty = sema.typeOf(ptr_ptr);
29381 const target = sema.mod.getTarget();
29382 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag()) {
29383 .Pointer => ptr_ptr_ty.elemType(),
29384 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(sema.mod)}),
30139 const ptr_ptr_child_ty = switch (ptr_ptr_ty.zigTypeTag(mod)) {
30140 .Pointer => ptr_ptr_ty.childType(mod),
30141 else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ptr_ty.fmt(mod)}),
2938530142 };
29386 const mod = sema.mod;
2938730143
2938830144 var array_ty = ptr_ptr_child_ty;
2938930145 var slice_ty = ptr_ptr_ty;
2939030146 var ptr_or_slice = ptr_ptr;
2939130147 var elem_ty: Type = undefined;
2939230148 var ptr_sentinel: ?Value = null;
29393 switch (ptr_ptr_child_ty.zigTypeTag()) {
30149 switch (ptr_ptr_child_ty.zigTypeTag(mod)) {
2939430150 .Array => {
29395 ptr_sentinel = ptr_ptr_child_ty.sentinel();
29396 elem_ty = ptr_ptr_child_ty.childType();
30151 ptr_sentinel = ptr_ptr_child_ty.sentinel(mod);
30152 elem_ty = ptr_ptr_child_ty.childType(mod);
2939730153 },
29398 .Pointer => switch (ptr_ptr_child_ty.ptrSize()) {
30154 .Pointer => switch (ptr_ptr_child_ty.ptrSize(mod)) {
2939930155 .One => {
29400 const double_child_ty = ptr_ptr_child_ty.childType();
29401 if (double_child_ty.zigTypeTag() == .Array) {
29402 ptr_sentinel = double_child_ty.sentinel();
30156 const double_child_ty = ptr_ptr_child_ty.childType(mod);
30157 if (double_child_ty.zigTypeTag(mod) == .Array) {
30158 ptr_sentinel = double_child_ty.sentinel(mod);
2940330159 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
2940430160 slice_ty = ptr_ptr_child_ty;
2940530161 array_ty = double_child_ty;
29406 elem_ty = double_child_ty.childType();
30162 elem_ty = double_child_ty.childType(mod);
2940730163 } else {
2940830164 return sema.fail(block, src, "slice of single-item pointer", .{});
2940930165 }
2941030166 },
2941130167 .Many, .C => {
29412 ptr_sentinel = ptr_ptr_child_ty.sentinel();
30168 ptr_sentinel = ptr_ptr_child_ty.sentinel(mod);
2941330169 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
2941430170 slice_ty = ptr_ptr_child_ty;
2941530171 array_ty = ptr_ptr_child_ty;
29416 elem_ty = ptr_ptr_child_ty.childType();
30172 elem_ty = ptr_ptr_child_ty.childType(mod);
2941730173
29418 if (ptr_ptr_child_ty.ptrSize() == .C) {
30174 if (ptr_ptr_child_ty.ptrSize(mod) == .C) {
2941930175 if (try sema.resolveDefinedValue(block, ptr_src, ptr_or_slice)) |ptr_val| {
29420 if (ptr_val.isNull()) {
30176 if (ptr_val.isNull(mod)) {
2942130177 return sema.fail(block, src, "slice of null pointer", .{});
2942230178 }
2942330179 }
2942430180 }
2942530181 },
2942630182 .Slice => {
29427 ptr_sentinel = ptr_ptr_child_ty.sentinel();
30183 ptr_sentinel = ptr_ptr_child_ty.sentinel(mod);
2942830184 ptr_or_slice = try sema.analyzeLoad(block, src, ptr_ptr, ptr_src);
2942930185 slice_ty = ptr_ptr_child_ty;
2943030186 array_ty = ptr_ptr_child_ty;
29431 elem_ty = ptr_ptr_child_ty.childType();
30187 elem_ty = ptr_ptr_child_ty.childType(mod);
2943230188 },
2943330189 },
2943430190 else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(mod)}),
2943530191 }
2943630192
29437 const ptr = if (slice_ty.isSlice())
30193 const ptr = if (slice_ty.isSlice(mod))
2943830194 try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty)
29439 else
29440 ptr_or_slice;
30195 else if (array_ty.zigTypeTag(mod) == .Array) ptr: {
30196 var manyptr_ty_key = mod.intern_pool.indexToKey(slice_ty.toIntern()).ptr_type;
30197 assert(manyptr_ty_key.child == array_ty.toIntern());
30198 assert(manyptr_ty_key.flags.size == .One);
30199 manyptr_ty_key.child = elem_ty.toIntern();
30200 manyptr_ty_key.flags.size = .Many;
30201 break :ptr try sema.coerceCompatiblePtrs(block, try mod.ptrType(manyptr_ty_key), ptr_or_slice, ptr_src);
30202 } else ptr_or_slice;
2944130203
2944230204 const start = try sema.coerce(block, Type.usize, uncasted_start, start_src);
2944330205 const new_ptr = try sema.analyzePtrArithmetic(block, src, ptr, start, .ptr_add, ptr_src, start_src);
30206 const new_ptr_ty = sema.typeOf(new_ptr);
2944430207
2944530208 // true if and only if the end index of the slice, implicitly or explicitly, equals
2944630209 // the length of the underlying object being sliced. we might learn the length of the
......@@ -29448,8 +30211,8 @@ fn analyzeSlice(
2944830211 // we might learn of the length because it is a comptime-known slice value.
2944930212 var end_is_len = uncasted_end_opt == .none;
2945030213 const end = e: {
29451 if (array_ty.zigTypeTag() == .Array) {
29452 const len_val = try Value.Tag.int_u64.create(sema.arena, array_ty.arrayLen());
30214 if (array_ty.zigTypeTag(mod) == .Array) {
30215 const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod));
2945330216
2945430217 if (!end_is_len) {
2945530218 const end = if (by_length) end: {
......@@ -29458,12 +30221,12 @@ fn analyzeSlice(
2945830221 break :end try sema.coerce(block, Type.usize, uncasted_end, end_src);
2945930222 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
2946030223 if (try sema.resolveMaybeUndefVal(end)) |end_val| {
29461 const len_s_val = try Value.Tag.int_u64.create(
29462 sema.arena,
29463 array_ty.arrayLenIncludingSentinel(),
30224 const len_s_val = try mod.intValue(
30225 Type.usize,
30226 array_ty.arrayLenIncludingSentinel(mod),
2946430227 );
2946530228 if (!(try sema.compareAll(end_val, .lte, len_s_val, Type.usize))) {
29466 const sentinel_label: []const u8 = if (array_ty.sentinel() != null)
30229 const sentinel_label: []const u8 = if (array_ty.sentinel(mod) != null)
2946730230 " +1 (sentinel)"
2946830231 else
2946930232 "";
......@@ -29491,7 +30254,7 @@ fn analyzeSlice(
2949130254 }
2949230255
2949330256 break :e try sema.addConstant(Type.usize, len_val);
29494 } else if (slice_ty.isSlice()) {
30257 } else if (slice_ty.isSlice(mod)) {
2949530258 if (!end_is_len) {
2949630259 const end = if (by_length) end: {
2949730260 const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
......@@ -29500,16 +30263,14 @@ fn analyzeSlice(
2950030263 } else try sema.coerce(block, Type.usize, uncasted_end_opt, end_src);
2950130264 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
2950230265 if (try sema.resolveMaybeUndefVal(ptr_or_slice)) |slice_val| {
29503 if (slice_val.isUndef()) {
30266 if (slice_val.isUndef(mod)) {
2950430267 return sema.fail(block, src, "slice of undefined", .{});
2950530268 }
29506 const has_sentinel = slice_ty.sentinel() != null;
29507 var int_payload: Value.Payload.U64 = .{
29508 .base = .{ .tag = .int_u64 },
29509 .data = slice_val.sliceLen(mod) + @boolToInt(has_sentinel),
29510 };
29511 const slice_len_val = Value.initPayload(&int_payload.base);
29512 if (!(try sema.compareAll(end_val, .lte, slice_len_val, Type.usize))) {
30269 const has_sentinel = slice_ty.sentinel(mod) != null;
30270 const slice_len = slice_val.sliceLen(mod);
30271 const len_plus_sent = slice_len + @boolToInt(has_sentinel);
30272 const slice_len_val_with_sentinel = try mod.intValue(Type.usize, len_plus_sent);
30273 if (!(try sema.compareAll(end_val, .lte, slice_len_val_with_sentinel, Type.usize))) {
2951330274 const sentinel_label: []const u8 = if (has_sentinel)
2951430275 " +1 (sentinel)"
2951530276 else
......@@ -29527,13 +30288,10 @@ fn analyzeSlice(
2952730288 );
2952830289 }
2952930290
29530 // If the slice has a sentinel, we subtract one so that
29531 // end_is_len is only true if it equals the length WITHOUT
29532 // the sentinel, so we don't add a sentinel type.
29533 if (has_sentinel) {
29534 int_payload.data -= 1;
29535 }
29536
30291 // If the slice has a sentinel, we consider end_is_len
30292 // is only true if it equals the length WITHOUT the
30293 // sentinel, so we don't add a sentinel type.
30294 const slice_len_val = try mod.intValue(Type.usize, slice_len);
2953730295 if (end_val.eql(slice_len_val, Type.usize, mod)) {
2953830296 end_is_len = true;
2953930297 }
......@@ -29569,11 +30327,12 @@ fn analyzeSlice(
2956930327 };
2957030328 const slice_sentinel = if (sentinel_opt != .none) sentinel else null;
2957130329
30330 var checked_start_lte_end = by_length;
30331 var runtime_src: ?LazySrcLoc = null;
30332
2957230333 // requirement: start <= end
29573 var need_start_gt_end_check = true;
2957430334 if (try sema.resolveDefinedValue(block, end_src, end)) |end_val| {
2957530335 if (try sema.resolveDefinedValue(block, start_src, start)) |start_val| {
29576 need_start_gt_end_check = false;
2957730336 if (!by_length and !(try sema.compareAll(start_val, .lte, end_val, Type.usize))) {
2957830337 return sema.fail(
2957930338 block,
......@@ -29585,14 +30344,18 @@ fn analyzeSlice(
2958530344 },
2958630345 );
2958730346 }
30347 checked_start_lte_end = true;
2958830348 if (try sema.resolveMaybeUndefVal(new_ptr)) |ptr_val| sentinel_check: {
2958930349 const expected_sentinel = sentinel orelse break :sentinel_check;
29590 const start_int = start_val.getUnsignedInt(sema.mod.getTarget()).?;
29591 const end_int = end_val.getUnsignedInt(sema.mod.getTarget()).?;
30350 const start_int = start_val.getUnsignedInt(mod).?;
30351 const end_int = end_val.getUnsignedInt(mod).?;
2959230352 const sentinel_index = try sema.usizeCast(block, end_src, end_int - start_int);
2959330353
29594 const elem_ptr = try ptr_val.elemPtr(sema.typeOf(new_ptr), sema.arena, sentinel_index, sema.mod);
29595 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty, false);
30354 const many_ptr_ty = try mod.manyConstPtrType(elem_ty);
30355 const many_ptr_val = try mod.getCoerced(ptr_val, many_ptr_ty);
30356 const elem_ptr_ty = try mod.singleConstPtrType(elem_ty);
30357 const elem_ptr = try many_ptr_val.elemPtr(elem_ptr_ty, sentinel_index, mod);
30358 const res = try sema.pointerDerefExtra(block, src, elem_ptr, elem_ty);
2959630359 const actual_sentinel = switch (res) {
2959730360 .runtime_load => break :sentinel_check,
2959830361 .val => |v| v,
......@@ -29600,36 +30363,49 @@ fn analyzeSlice(
2960030363 block,
2960130364 src,
2960230365 "comptime dereference requires '{}' to have a well-defined layout, but it does not.",
29603 .{ty.fmt(sema.mod)},
30366 .{ty.fmt(mod)},
2960430367 ),
2960530368 .out_of_bounds => |ty| return sema.fail(
2960630369 block,
2960730370 end_src,
2960830371 "slice end index {d} exceeds bounds of containing decl of type '{}'",
29609 .{ end_int, ty.fmt(sema.mod) },
30372 .{ end_int, ty.fmt(mod) },
2961030373 ),
2961130374 };
2961230375
29613 if (!actual_sentinel.eql(expected_sentinel, elem_ty, sema.mod)) {
30376 if (!actual_sentinel.eql(expected_sentinel, elem_ty, mod)) {
2961430377 const msg = msg: {
2961530378 const msg = try sema.errMsg(block, src, "value in memory does not match slice sentinel", .{});
2961630379 errdefer msg.destroy(sema.gpa);
2961730380 try sema.errNote(block, src, msg, "expected '{}', found '{}'", .{
29618 expected_sentinel.fmtValue(elem_ty, sema.mod),
29619 actual_sentinel.fmtValue(elem_ty, sema.mod),
30381 expected_sentinel.fmtValue(elem_ty, mod),
30382 actual_sentinel.fmtValue(elem_ty, mod),
2962030383 });
2962130384
2962230385 break :msg msg;
2962330386 };
2962430387 return sema.failWithOwnedErrorMsg(msg);
2962530388 }
30389 } else {
30390 runtime_src = ptr_src;
2962630391 }
30392 } else {
30393 runtime_src = start_src;
2962730394 }
30395 } else {
30396 runtime_src = end_src;
2962830397 }
2962930398
29630 if (!by_length and block.wantSafety() and !block.is_comptime and need_start_gt_end_check) {
30399 if (!checked_start_lte_end and block.wantSafety() and !block.is_comptime) {
2963130400 // requirement: start <= end
29632 try sema.panicStartGreaterThanEnd(block, start, end);
30401 assert(!block.is_comptime);
30402 try sema.requireRuntimeBlock(block, src, runtime_src.?);
30403 const ok = try block.addBinOp(.cmp_lte, start, end);
30404 if (!sema.mod.comp.formatted_panics) {
30405 try sema.addSafetyCheck(block, ok, .start_index_greater_than_end);
30406 } else {
30407 try sema.safetyCheckFormatted(block, ok, "panicStartGreaterThanEnd", &.{ start, end });
30408 }
2963330409 }
2963430410 const new_len = if (by_length)
2963530411 try sema.coerce(block, Type.usize, uncasted_end_opt, end_src)
......@@ -29637,11 +30413,11 @@ fn analyzeSlice(
2963730413 try sema.analyzeArithmetic(block, .sub, end, start, src, end_src, start_src, false);
2963830414 const opt_new_len_val = try sema.resolveDefinedValue(block, src, new_len);
2963930415
29640 const new_ptr_ty_info = sema.typeOf(new_ptr).ptrInfo().data;
29641 const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize() != .C;
30416 const new_ptr_ty_info = new_ptr_ty.ptrInfo(mod);
30417 const new_allowzero = new_ptr_ty_info.@"allowzero" and sema.typeOf(ptr).ptrSize(mod) != .C;
2964230418
2964330419 if (opt_new_len_val) |new_len_val| {
29644 const new_len_int = new_len_val.toUnsignedInt(target);
30420 const new_len_int = new_len_val.toUnsignedInt(mod);
2964530421
2964630422 const return_ty = try Type.ptr(sema.arena, mod, .{
2964730423 .pointee_type = try Type.array(sema.arena, new_len_int, sentinel, elem_ty, mod),
......@@ -29659,14 +30435,14 @@ fn analyzeSlice(
2965930435 const result = try block.addBitCast(return_ty, new_ptr);
2966030436 if (block.wantSafety()) {
2966130437 // requirement: slicing C ptr is non-null
29662 if (ptr_ptr_child_ty.isCPtr()) {
30438 if (ptr_ptr_child_ty.isCPtr(mod)) {
2966330439 const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);
2966430440 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
2966530441 }
2966630442
29667 if (slice_ty.isSlice()) {
30443 if (slice_ty.isSlice(mod)) {
2966830444 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
29669 const actual_len = if (slice_ty.sentinel() == null)
30445 const actual_len = if (slice_ty.sentinel(mod) == null)
2967030446 slice_len_inst
2967130447 else
2967230448 try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
......@@ -29685,8 +30461,11 @@ fn analyzeSlice(
2968530461 return result;
2968630462 };
2968730463
29688 if (!new_ptr_val.isUndef()) {
29689 return sema.addConstant(return_ty, new_ptr_val);
30464 if (!new_ptr_val.isUndef(mod)) {
30465 return sema.addConstant(return_ty, try mod.getCoerced(
30466 (try new_ptr_val.intern(new_ptr_ty, mod)).toValue(),
30467 return_ty,
30468 ));
2969030469 }
2969130470
2969230471 // Special case: @as([]i32, undefined)[x..x]
......@@ -29708,25 +30487,18 @@ fn analyzeSlice(
2970830487 .size = .Slice,
2970930488 });
2971030489
29711 const runtime_src = if ((try sema.resolveMaybeUndefVal(ptr_or_slice)) == null)
29712 ptr_src
29713 else if ((try sema.resolveMaybeUndefVal(start)) == null)
29714 start_src
29715 else
29716 end_src;
29717
29718 try sema.requireRuntimeBlock(block, src, runtime_src);
30490 try sema.requireRuntimeBlock(block, src, runtime_src.?);
2971930491 if (block.wantSafety()) {
2972030492 // requirement: slicing C ptr is non-null
29721 if (ptr_ptr_child_ty.isCPtr()) {
30493 if (ptr_ptr_child_ty.isCPtr(mod)) {
2972230494 const is_non_null = try sema.analyzeIsNull(block, ptr_src, ptr, true);
2972330495 try sema.addSafetyCheck(block, is_non_null, .unwrap_null);
2972430496 }
2972530497
2972630498 // requirement: end <= len
29727 const opt_len_inst = if (array_ty.zigTypeTag() == .Array)
29728 try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel())
29729 else if (slice_ty.isSlice()) blk: {
30499 const opt_len_inst = if (array_ty.zigTypeTag(mod) == .Array)
30500 try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel(mod))
30501 else if (slice_ty.isSlice(mod)) blk: {
2973030502 if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| {
2973130503 // we don't need to add one for sentinels because the
2973230504 // underlying value data includes the sentinel
......@@ -29734,7 +30506,7 @@ fn analyzeSlice(
2973430506 }
2973530507
2973630508 const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice);
29737 if (slice_ty.sentinel() == null) break :blk slice_len_inst;
30509 if (slice_ty.sentinel(mod) == null) break :blk slice_len_inst;
2973830510
2973930511 // we have to add one because slice lengths don't include the sentinel
2974030512 break :blk try sema.analyzeArithmetic(block, .add, slice_len_inst, .one, src, end_src, end_src, true);
......@@ -29778,15 +30550,16 @@ fn cmpNumeric(
2977830550 lhs_src: LazySrcLoc,
2977930551 rhs_src: LazySrcLoc,
2978030552) CompileError!Air.Inst.Ref {
30553 const mod = sema.mod;
2978130554 const lhs_ty = sema.typeOf(uncasted_lhs);
2978230555 const rhs_ty = sema.typeOf(uncasted_rhs);
2978330556
29784 assert(lhs_ty.isNumeric());
29785 assert(rhs_ty.isNumeric());
30557 assert(lhs_ty.isNumeric(mod));
30558 assert(rhs_ty.isNumeric(mod));
2978630559
29787 const lhs_ty_tag = lhs_ty.zigTypeTag();
29788 const rhs_ty_tag = rhs_ty.zigTypeTag();
29789 const target = sema.mod.getTarget();
30560 const lhs_ty_tag = lhs_ty.zigTypeTag(mod);
30561 const rhs_ty_tag = rhs_ty.zigTypeTag(mod);
30562 const target = mod.getTarget();
2979030563
2979130564 // One exception to heterogeneous comparison: comptime_float needs to
2979230565 // coerce to fixed-width float.
......@@ -29805,49 +30578,45 @@ fn cmpNumeric(
2980530578 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {
2980630579 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
2980730580 // Compare ints: const vs. undefined (or vice versa)
29808 if (!lhs_val.isUndef() and (lhs_ty.isInt() or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt() and rhs_val.isUndef()) {
29809 try sema.resolveLazyValue(lhs_val);
29810 if (sema.compareIntsOnlyPossibleResult(target, lhs_val, op, rhs_ty)) |res| {
30581 if (!lhs_val.isUndef(mod) and (lhs_ty.isInt(mod) or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt(mod) and rhs_val.isUndef(mod)) {
30582 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| {
2981130583 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
2981230584 }
29813 } else if (!rhs_val.isUndef() and (rhs_ty.isInt() or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt() and lhs_val.isUndef()) {
29814 try sema.resolveLazyValue(rhs_val);
29815 if (sema.compareIntsOnlyPossibleResult(target, rhs_val, op.reverse(), lhs_ty)) |res| {
30585 } else if (!rhs_val.isUndef(mod) and (rhs_ty.isInt(mod) or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt(mod) and lhs_val.isUndef(mod)) {
30586 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| {
2981630587 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
2981730588 }
2981830589 }
2981930590
29820 if (lhs_val.isUndef() or rhs_val.isUndef()) {
30591 if (lhs_val.isUndef(mod) or rhs_val.isUndef(mod)) {
2982130592 return sema.addConstUndef(Type.bool);
2982230593 }
29823 if (lhs_val.isNan() or rhs_val.isNan()) {
30594 if (lhs_val.isNan(mod) or rhs_val.isNan(mod)) {
2982430595 if (op == std.math.CompareOperator.neq) {
2982530596 return Air.Inst.Ref.bool_true;
2982630597 } else {
2982730598 return Air.Inst.Ref.bool_false;
2982830599 }
2982930600 }
29830 if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, target, sema)) {
30601 if (try Value.compareHeteroAdvanced(lhs_val, op, rhs_val, mod, sema)) {
2983130602 return Air.Inst.Ref.bool_true;
2983230603 } else {
2983330604 return Air.Inst.Ref.bool_false;
2983430605 }
2983530606 } else {
29836 if (!lhs_val.isUndef() and (lhs_ty.isInt() or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt()) {
30607 if (!lhs_val.isUndef(mod) and (lhs_ty.isInt(mod) or lhs_ty_tag == .ComptimeInt) and rhs_ty.isInt(mod)) {
2983730608 // Compare ints: const vs. var
29838 try sema.resolveLazyValue(lhs_val);
29839 if (sema.compareIntsOnlyPossibleResult(target, lhs_val, op, rhs_ty)) |res| {
30609 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(lhs_val), op, rhs_ty)) |res| {
2984030610 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
2984130611 }
2984230612 }
2984330613 break :src rhs_src;
2984430614 }
2984530615 } else {
29846 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
29847 if (!rhs_val.isUndef() and (rhs_ty.isInt() or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt()) {
30616 if (try sema.resolveMaybeUndefLazyVal(rhs)) |rhs_val| {
30617 if (!rhs_val.isUndef(mod) and (rhs_ty.isInt(mod) or rhs_ty_tag == .ComptimeInt) and lhs_ty.isInt(mod)) {
2984830618 // Compare ints: var vs. const
29849 try sema.resolveLazyValue(rhs_val);
29850 if (sema.compareIntsOnlyPossibleResult(target, rhs_val, op.reverse(), lhs_ty)) |res| {
30619 if (try sema.compareIntsOnlyPossibleResult(try sema.resolveLazyValue(rhs_val), op.reverse(), lhs_ty)) |res| {
2985130620 return if (res) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false;
2985230621 }
2985330622 }
......@@ -29901,32 +30670,31 @@ fn cmpNumeric(
2990130670 const lhs_is_signed = if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val|
2990230671 !(try lhs_val.compareAllWithZeroAdvanced(.gte, sema))
2990330672 else
29904 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt());
30673 (lhs_ty.isRuntimeFloat() or lhs_ty.isSignedInt(mod));
2990530674 const rhs_is_signed = if (try sema.resolveDefinedValue(block, rhs_src, rhs)) |rhs_val|
2990630675 !(try rhs_val.compareAllWithZeroAdvanced(.gte, sema))
2990730676 else
29908 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt());
30677 (rhs_ty.isRuntimeFloat() or rhs_ty.isSignedInt(mod));
2990930678 const dest_int_is_signed = lhs_is_signed or rhs_is_signed;
2991030679
2991130680 var dest_float_type: ?Type = null;
2991230681
2991330682 var lhs_bits: usize = undefined;
29914 if (try sema.resolveMaybeUndefVal(lhs)) |lhs_val| {
29915 try sema.resolveLazyValue(lhs_val);
29916 if (lhs_val.isUndef())
30683 if (try sema.resolveMaybeUndefLazyVal(lhs)) |lhs_val| {
30684 if (lhs_val.isUndef(mod))
2991730685 return sema.addConstUndef(Type.bool);
29918 if (lhs_val.isNan()) switch (op) {
30686 if (lhs_val.isNan(mod)) switch (op) {
2991930687 .neq => return Air.Inst.Ref.bool_true,
2992030688 else => return Air.Inst.Ref.bool_false,
2992130689 };
29922 if (lhs_val.isInf()) switch (op) {
30690 if (lhs_val.isInf(mod)) switch (op) {
2992330691 .neq => return Air.Inst.Ref.bool_true,
2992430692 .eq => return Air.Inst.Ref.bool_false,
29925 .gt, .gte => return if (lhs_val.isNegativeInf()) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true,
29926 .lt, .lte => return if (lhs_val.isNegativeInf()) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false,
30693 .gt, .gte => return if (lhs_val.isNegativeInf(mod)) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true,
30694 .lt, .lte => return if (lhs_val.isNegativeInf(mod)) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false,
2992730695 };
2992830696 if (!rhs_is_signed) {
29929 switch (lhs_val.orderAgainstZero()) {
30697 switch (lhs_val.orderAgainstZero(mod)) {
2993030698 .gt => {},
2993130699 .eq => switch (op) { // LHS = 0, RHS is unsigned
2993230700 .lte => return Air.Inst.Ref.bool_true,
......@@ -29940,7 +30708,7 @@ fn cmpNumeric(
2994030708 }
2994130709 }
2994230710 if (lhs_is_float) {
29943 if (lhs_val.floatHasFraction()) {
30711 if (lhs_val.floatHasFraction(mod)) {
2994430712 switch (op) {
2994530713 .eq => return Air.Inst.Ref.bool_false,
2994630714 .neq => return Air.Inst.Ref.bool_true,
......@@ -29948,9 +30716,9 @@ fn cmpNumeric(
2994830716 }
2994930717 }
2995030718
29951 var bigint = try float128IntPartToBigInt(sema.gpa, lhs_val.toFloat(f128));
30719 var bigint = try float128IntPartToBigInt(sema.gpa, lhs_val.toFloat(f128, mod));
2995230720 defer bigint.deinit();
29953 if (lhs_val.floatHasFraction()) {
30721 if (lhs_val.floatHasFraction(mod)) {
2995430722 if (lhs_is_signed) {
2995530723 try bigint.addScalar(&bigint, -1);
2995630724 } else {
......@@ -29959,33 +30727,32 @@ fn cmpNumeric(
2995930727 }
2996030728 lhs_bits = bigint.toConst().bitCountTwosComp();
2996130729 } else {
29962 lhs_bits = lhs_val.intBitCountTwosComp(target);
30730 lhs_bits = lhs_val.intBitCountTwosComp(mod);
2996330731 }
2996430732 lhs_bits += @boolToInt(!lhs_is_signed and dest_int_is_signed);
2996530733 } else if (lhs_is_float) {
2996630734 dest_float_type = lhs_ty;
2996730735 } else {
29968 const int_info = lhs_ty.intInfo(target);
30736 const int_info = lhs_ty.intInfo(mod);
2996930737 lhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
2997030738 }
2997130739
2997230740 var rhs_bits: usize = undefined;
29973 if (try sema.resolveMaybeUndefVal(rhs)) |rhs_val| {
29974 try sema.resolveLazyValue(rhs_val);
29975 if (rhs_val.isUndef())
30741 if (try sema.resolveMaybeUndefLazyVal(rhs)) |rhs_val| {
30742 if (rhs_val.isUndef(mod))
2997630743 return sema.addConstUndef(Type.bool);
29977 if (rhs_val.isNan()) switch (op) {
30744 if (rhs_val.isNan(mod)) switch (op) {
2997830745 .neq => return Air.Inst.Ref.bool_true,
2997930746 else => return Air.Inst.Ref.bool_false,
2998030747 };
29981 if (rhs_val.isInf()) switch (op) {
30748 if (rhs_val.isInf(mod)) switch (op) {
2998230749 .neq => return Air.Inst.Ref.bool_true,
2998330750 .eq => return Air.Inst.Ref.bool_false,
29984 .gt, .gte => return if (rhs_val.isNegativeInf()) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false,
29985 .lt, .lte => return if (rhs_val.isNegativeInf()) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true,
30751 .gt, .gte => return if (rhs_val.isNegativeInf(mod)) Air.Inst.Ref.bool_true else Air.Inst.Ref.bool_false,
30752 .lt, .lte => return if (rhs_val.isNegativeInf(mod)) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true,
2998630753 };
2998730754 if (!lhs_is_signed) {
29988 switch (rhs_val.orderAgainstZero()) {
30755 switch (rhs_val.orderAgainstZero(mod)) {
2998930756 .gt => {},
2999030757 .eq => switch (op) { // RHS = 0, LHS is unsigned
2999130758 .gte => return Air.Inst.Ref.bool_true,
......@@ -29999,7 +30766,7 @@ fn cmpNumeric(
2999930766 }
3000030767 }
3000130768 if (rhs_is_float) {
30002 if (rhs_val.floatHasFraction()) {
30769 if (rhs_val.floatHasFraction(mod)) {
3000330770 switch (op) {
3000430771 .eq => return Air.Inst.Ref.bool_false,
3000530772 .neq => return Air.Inst.Ref.bool_true,
......@@ -30007,9 +30774,9 @@ fn cmpNumeric(
3000730774 }
3000830775 }
3000930776
30010 var bigint = try float128IntPartToBigInt(sema.gpa, rhs_val.toFloat(f128));
30777 var bigint = try float128IntPartToBigInt(sema.gpa, rhs_val.toFloat(f128, mod));
3001130778 defer bigint.deinit();
30012 if (rhs_val.floatHasFraction()) {
30779 if (rhs_val.floatHasFraction(mod)) {
3001330780 if (rhs_is_signed) {
3001430781 try bigint.addScalar(&bigint, -1);
3001530782 } else {
......@@ -30018,13 +30785,13 @@ fn cmpNumeric(
3001830785 }
3001930786 rhs_bits = bigint.toConst().bitCountTwosComp();
3002030787 } else {
30021 rhs_bits = rhs_val.intBitCountTwosComp(target);
30788 rhs_bits = rhs_val.intBitCountTwosComp(mod);
3002230789 }
3002330790 rhs_bits += @boolToInt(!rhs_is_signed and dest_int_is_signed);
3002430791 } else if (rhs_is_float) {
3002530792 dest_float_type = rhs_ty;
3002630793 } else {
30027 const int_info = rhs_ty.intInfo(target);
30794 const int_info = rhs_ty.intInfo(mod);
3002830795 rhs_bits = int_info.bits + @boolToInt(int_info.signedness == .unsigned and dest_int_is_signed);
3002930796 }
3003030797
......@@ -30032,7 +30799,7 @@ fn cmpNumeric(
3003230799 const max_bits = std.math.max(lhs_bits, rhs_bits);
3003330800 const casted_bits = std.math.cast(u16, max_bits) orelse return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits});
3003430801 const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned;
30035 break :blk try Module.makeIntType(sema.arena, signedness, casted_bits);
30802 break :blk try mod.intType(signedness, casted_bits);
3003630803 };
3003730804 const casted_lhs = try sema.coerce(block, dest_ty, lhs, lhs_src);
3003830805 const casted_rhs = try sema.coerce(block, dest_ty, rhs, rhs_src);
......@@ -30040,13 +30807,20 @@ fn cmpNumeric(
3004030807 return block.addBinOp(Air.Inst.Tag.fromCmpOp(op, block.float_mode == .Optimized), casted_lhs, casted_rhs);
3004130808}
3004230809
30043/// Asserts that LHS value is an int or comptime int and not undefined, and that RHS type is an int.
30044/// Given a const LHS and an unknown RHS, attempt to determine whether `op` has a guaranteed result.
30810/// Asserts that LHS value is an int or comptime int and not undefined, and
30811/// that RHS type is an int. Given a const LHS and an unknown RHS, attempt to
30812/// determine whether `op` has a guaranteed result.
3004530813/// If it cannot be determined, returns null.
3004630814/// Otherwise returns a bool for the guaranteed comparison operation.
30047fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value, op: std.math.CompareOperator, rhs_ty: Type) ?bool {
30048 const rhs_info = rhs_ty.intInfo(target);
30049 const vs_zero = lhs_val.orderAgainstZeroAdvanced(sema) catch unreachable;
30815fn compareIntsOnlyPossibleResult(
30816 sema: *Sema,
30817 lhs_val: Value,
30818 op: std.math.CompareOperator,
30819 rhs_ty: Type,
30820) Allocator.Error!?bool {
30821 const mod = sema.mod;
30822 const rhs_info = rhs_ty.intInfo(mod);
30823 const vs_zero = lhs_val.orderAgainstZeroAdvanced(mod, sema) catch unreachable;
3005030824 const is_zero = vs_zero == .eq;
3005130825 const is_negative = vs_zero == .lt;
3005230826 const is_positive = vs_zero == .gt;
......@@ -30078,7 +30852,7 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value
3007830852 };
3007930853
3008030854 const sign_adj = @boolToInt(!is_negative and rhs_info.signedness == .signed);
30081 const req_bits = lhs_val.intBitCountTwosComp(target) + sign_adj;
30855 const req_bits = lhs_val.intBitCountTwosComp(mod) + sign_adj;
3008230856
3008330857 // No sized type can have more than 65535 bits.
3008430858 // The RHS type operand is either a runtime value or sized (but undefined) constant.
......@@ -30111,12 +30885,11 @@ fn compareIntsOnlyPossibleResult(sema: *Sema, target: std.Target, lhs_val: Value
3011130885 .max = false,
3011230886 };
3011330887
30114 var ty_buffer: Type.Payload.Bits = .{
30115 .base = .{ .tag = if (is_negative) .int_signed else .int_unsigned },
30116 .data = @intCast(u16, req_bits),
30117 };
30118 const ty = Type.initPayload(&ty_buffer.base);
30119 const pop_count = lhs_val.popCount(ty, target);
30888 const ty = try mod.intType(
30889 if (is_negative) .signed else .unsigned,
30890 @intCast(u16, req_bits),
30891 );
30892 const pop_count = lhs_val.popCount(ty, mod);
3012030893
3012130894 if (is_negative) {
3012230895 break :edge .{
......@@ -30152,22 +30925,26 @@ fn cmpVector(
3015230925 lhs_src: LazySrcLoc,
3015330926 rhs_src: LazySrcLoc,
3015430927) CompileError!Air.Inst.Ref {
30928 const mod = sema.mod;
3015530929 const lhs_ty = sema.typeOf(lhs);
3015630930 const rhs_ty = sema.typeOf(rhs);
30157 assert(lhs_ty.zigTypeTag() == .Vector);
30158 assert(rhs_ty.zigTypeTag() == .Vector);
30931 assert(lhs_ty.zigTypeTag(mod) == .Vector);
30932 assert(rhs_ty.zigTypeTag(mod) == .Vector);
3015930933 try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
3016030934
3016130935 const resolved_ty = try sema.resolvePeerTypes(block, src, &.{ lhs, rhs }, .{ .override = &.{ lhs_src, rhs_src } });
3016230936 const casted_lhs = try sema.coerce(block, resolved_ty, lhs, lhs_src);
3016330937 const casted_rhs = try sema.coerce(block, resolved_ty, rhs, rhs_src);
3016430938
30165 const result_ty = try Type.vector(sema.arena, lhs_ty.vectorLen(), Type.bool);
30939 const result_ty = try mod.vectorType(.{
30940 .len = lhs_ty.vectorLen(mod),
30941 .child = .bool_type,
30942 });
3016630943
3016730944 const runtime_src: LazySrcLoc = src: {
3016830945 if (try sema.resolveMaybeUndefVal(casted_lhs)) |lhs_val| {
3016930946 if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| {
30170 if (lhs_val.isUndef() or rhs_val.isUndef()) {
30947 if (lhs_val.isUndef(mod) or rhs_val.isUndef(mod)) {
3017130948 return sema.addConstUndef(result_ty);
3017230949 }
3017330950 const cmp_val = try sema.compareVector(lhs_val, op, rhs_val, resolved_ty);
......@@ -30192,7 +30969,10 @@ fn wrapOptional(
3019230969 inst_src: LazySrcLoc,
3019330970) !Air.Inst.Ref {
3019430971 if (try sema.resolveMaybeUndefVal(inst)) |val| {
30195 return sema.addConstant(dest_ty, try Value.Tag.opt_payload.create(sema.arena, val));
30972 return sema.addConstant(dest_ty, (try sema.mod.intern(.{ .opt = .{
30973 .ty = dest_ty.toIntern(),
30974 .val = val.toIntern(),
30975 } })).toValue());
3019630976 }
3019730977
3019830978 try sema.requireRuntimeBlock(block, inst_src, null);
......@@ -30206,10 +30986,14 @@ fn wrapErrorUnionPayload(
3020630986 inst: Air.Inst.Ref,
3020730987 inst_src: LazySrcLoc,
3020830988) !Air.Inst.Ref {
30209 const dest_payload_ty = dest_ty.errorUnionPayload();
30989 const mod = sema.mod;
30990 const dest_payload_ty = dest_ty.errorUnionPayload(mod);
3021030991 const coerced = try sema.coerceExtra(block, dest_payload_ty, inst, inst_src, .{ .report_err = false });
3021130992 if (try sema.resolveMaybeUndefVal(coerced)) |val| {
30212 return sema.addConstant(dest_ty, try Value.Tag.eu_payload.create(sema.arena, val));
30993 return sema.addConstant(dest_ty, (try mod.intern(.{ .error_union = .{
30994 .ty = dest_ty.toIntern(),
30995 .val = .{ .payload = try val.intern(dest_payload_ty, mod) },
30996 } })).toValue());
3021330997 }
3021430998 try sema.requireRuntimeBlock(block, inst_src, null);
3021530999 try sema.queueFullTypeResolution(dest_payload_ty);
......@@ -30223,48 +31007,41 @@ fn wrapErrorUnionSet(
3022331007 inst: Air.Inst.Ref,
3022431008 inst_src: LazySrcLoc,
3022531009) !Air.Inst.Ref {
31010 const mod = sema.mod;
31011 const ip = &mod.intern_pool;
3022631012 const inst_ty = sema.typeOf(inst);
30227 const dest_err_set_ty = dest_ty.errorUnionSet();
31013 const dest_err_set_ty = dest_ty.errorUnionSet(mod);
3022831014 if (try sema.resolveMaybeUndefVal(inst)) |val| {
30229 switch (dest_err_set_ty.tag()) {
30230 .anyerror => {},
30231 .error_set_single => ok: {
30232 const expected_name = val.castTag(.@"error").?.data.name;
30233 const n = dest_err_set_ty.castTag(.error_set_single).?.data;
30234 if (mem.eql(u8, expected_name, n)) break :ok;
30235 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30236 },
30237 .error_set => {
30238 const expected_name = val.castTag(.@"error").?.data.name;
30239 const error_set = dest_err_set_ty.castTag(.error_set).?.data;
30240 if (!error_set.names.contains(expected_name)) {
31015 switch (dest_err_set_ty.toIntern()) {
31016 .anyerror_type => {},
31017 else => switch (ip.indexToKey(dest_err_set_ty.toIntern())) {
31018 .error_set_type => |error_set_type| ok: {
31019 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
31020 if (error_set_type.nameIndex(ip, expected_name) != null) break :ok;
3024131021 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30242 }
30243 },
30244 .error_set_inferred => ok: {
30245 const expected_name = val.castTag(.@"error").?.data.name;
30246 const ies = dest_err_set_ty.castTag(.error_set_inferred).?.data;
31022 },
31023 .inferred_error_set_type => |ies_index| ok: {
31024 const ies = mod.inferredErrorSetPtr(ies_index);
31025 const expected_name = mod.intern_pool.indexToKey(val.toIntern()).err.name;
3024731026
30248 // We carefully do this in an order that avoids unnecessarily
30249 // resolving the destination error set type.
30250 if (ies.is_anyerror) break :ok;
30251 if (ies.errors.contains(expected_name)) break :ok;
30252 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) {
30253 break :ok;
30254 }
31027 // We carefully do this in an order that avoids unnecessarily
31028 // resolving the destination error set type.
31029 if (ies.is_anyerror) break :ok;
31030
31031 if (ies.errors.contains(expected_name)) break :ok;
31032 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, dest_err_set_ty, inst_ty, inst_src, inst_src)) break :ok;
3025531033
30256 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30257 },
30258 .error_set_merged => {
30259 const expected_name = val.castTag(.@"error").?.data.name;
30260 const error_set = dest_err_set_ty.castTag(.error_set_merged).?.data;
30261 if (!error_set.contains(expected_name)) {
3026231034 return sema.failWithErrorSetCodeMissing(block, inst_src, dest_err_set_ty, inst_ty);
30263 }
31035 },
31036 else => unreachable,
3026431037 },
30265 else => unreachable,
3026631038 }
30267 return sema.addConstant(dest_ty, val);
31039 return sema.addConstant(dest_ty, (try mod.intern(.{ .error_union = .{
31040 .ty = dest_ty.toIntern(),
31041 .val = .{
31042 .err_name = mod.intern_pool.indexToKey(try val.intern(dest_err_set_ty, mod)).err.name,
31043 },
31044 } })).toValue());
3026831045 }
3026931046
3027031047 try sema.requireRuntimeBlock(block, inst_src, null);
......@@ -30279,11 +31056,12 @@ fn unionToTag(
3027931056 un: Air.Inst.Ref,
3028031057 un_src: LazySrcLoc,
3028131058) !Air.Inst.Ref {
31059 const mod = sema.mod;
3028231060 if ((try sema.typeHasOnePossibleValue(enum_ty))) |opv| {
3028331061 return sema.addConstant(enum_ty, opv);
3028431062 }
3028531063 if (try sema.resolveMaybeUndefVal(un)) |un_val| {
30286 return sema.addConstant(enum_ty, un_val.unionTag());
31064 return sema.addConstant(enum_ty, un_val.unionTag(mod));
3028731065 }
3028831066 try sema.requireRuntimeBlock(block, un_src, null);
3028931067 return block.addTyOp(.get_union_tag, enum_ty, un);
......@@ -30296,16 +31074,17 @@ fn resolvePeerTypes(
3029631074 instructions: []const Air.Inst.Ref,
3029731075 candidate_srcs: Module.PeerTypeCandidateSrc,
3029831076) !Type {
31077 const mod = sema.mod;
3029931078 switch (instructions.len) {
30300 0 => return Type.initTag(.noreturn),
31079 0 => return Type.noreturn,
3030131080 1 => return sema.typeOf(instructions[0]),
3030231081 else => {},
3030331082 }
3030431083
30305 const target = sema.mod.getTarget();
31084 const target = mod.getTarget();
3030631085
3030731086 var chosen = instructions[0];
30308 // If this is non-null then it does the following thing, depending on the chosen zigTypeTag().
31087 // If this is non-null then it does the following thing, depending on the chosen zigTypeTag(mod).
3030931088 // * ErrorSet: this is an override
3031031089 // * ErrorUnion: this is an override of the error set only
3031131090 // * other: at the end we make an ErrorUnion with the other thing and this
......@@ -30318,8 +31097,8 @@ fn resolvePeerTypes(
3031831097 const candidate_ty = sema.typeOf(candidate);
3031931098 const chosen_ty = sema.typeOf(chosen);
3032031099
30321 const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison();
30322 const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison();
31100 const candidate_ty_tag = try candidate_ty.zigTypeTagOrPoison(mod);
31101 const chosen_ty_tag = try chosen_ty.zigTypeTagOrPoison(mod);
3032331102
3032431103 // If the candidate can coerce into our chosen type, we're done.
3032531104 // If the chosen type can coerce into the candidate, use that.
......@@ -30347,8 +31126,8 @@ fn resolvePeerTypes(
3034731126 continue;
3034831127 },
3034931128 .Int => {
30350 const chosen_info = chosen_ty.intInfo(target);
30351 const candidate_info = candidate_ty.intInfo(target);
31129 const chosen_info = chosen_ty.intInfo(mod);
31130 const candidate_info = candidate_ty.intInfo(mod);
3035231131
3035331132 if (chosen_info.bits < candidate_info.bits) {
3035431133 chosen = candidate;
......@@ -30356,12 +31135,12 @@ fn resolvePeerTypes(
3035631135 }
3035731136 continue;
3035831137 },
30359 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
31138 .Pointer => if (chosen_ty.ptrSize(mod) == .C) continue,
3036031139 else => {},
3036131140 },
3036231141 .ComptimeInt => switch (chosen_ty_tag) {
3036331142 .Int, .Float, .ComptimeFloat => continue,
30364 .Pointer => if (chosen_ty.ptrSize() == .C) continue,
31143 .Pointer => if (chosen_ty.ptrSize(mod) == .C) continue,
3036531144 else => {},
3036631145 },
3036731146 .Float => switch (chosen_ty_tag) {
......@@ -30426,11 +31205,11 @@ fn resolvePeerTypes(
3042631205 continue;
3042731206 }
3042831207
30429 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
31208 err_set_ty = try sema.errorSetMerge(chosen_set_ty, candidate_ty);
3043031209 continue;
3043131210 },
3043231211 .ErrorUnion => {
30433 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet();
31212 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet(mod);
3043431213
3043531214 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_ty, src, src)) {
3043631215 continue;
......@@ -30440,7 +31219,7 @@ fn resolvePeerTypes(
3044031219 continue;
3044131220 }
3044231221
30443 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
31222 err_set_ty = try sema.errorSetMerge(chosen_set_ty, candidate_ty);
3044431223 continue;
3044531224 },
3044631225 else => {
......@@ -30453,7 +31232,7 @@ fn resolvePeerTypes(
3045331232 continue;
3045431233 }
3045531234
30456 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_ty);
31235 err_set_ty = try sema.errorSetMerge(chosen_set_ty, candidate_ty);
3045731236 continue;
3045831237 } else {
3045931238 err_set_ty = candidate_ty;
......@@ -30464,14 +31243,14 @@ fn resolvePeerTypes(
3046431243 .ErrorUnion => switch (chosen_ty_tag) {
3046531244 .ErrorSet => {
3046631245 const chosen_set_ty = err_set_ty orelse chosen_ty;
30467 const candidate_set_ty = candidate_ty.errorUnionSet();
31246 const candidate_set_ty = candidate_ty.errorUnionSet(mod);
3046831247
3046931248 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {
3047031249 err_set_ty = chosen_set_ty;
3047131250 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {
3047231251 err_set_ty = null;
3047331252 } else {
30474 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_set_ty);
31253 err_set_ty = try sema.errorSetMerge(chosen_set_ty, candidate_set_ty);
3047531254 }
3047631255 chosen = candidate;
3047731256 chosen_i = candidate_i + 1;
......@@ -30479,8 +31258,8 @@ fn resolvePeerTypes(
3047931258 },
3048031259
3048131260 .ErrorUnion => {
30482 const chosen_payload_ty = chosen_ty.errorUnionPayload();
30483 const candidate_payload_ty = candidate_ty.errorUnionPayload();
31261 const chosen_payload_ty = chosen_ty.errorUnionPayload(mod);
31262 const candidate_payload_ty = candidate_ty.errorUnionPayload(mod);
3048431263
3048531264 const coerce_chosen = (try sema.coerceInMemoryAllowed(block, chosen_payload_ty, candidate_payload_ty, false, target, src, src)) == .ok;
3048631265 const coerce_candidate = (try sema.coerceInMemoryAllowed(block, candidate_payload_ty, chosen_payload_ty, false, target, src, src)) == .ok;
......@@ -30494,15 +31273,15 @@ fn resolvePeerTypes(
3049431273 chosen_i = candidate_i + 1;
3049531274 }
3049631275
30497 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet();
30498 const candidate_set_ty = candidate_ty.errorUnionSet();
31276 const chosen_set_ty = err_set_ty orelse chosen_ty.errorUnionSet(mod);
31277 const candidate_set_ty = candidate_ty.errorUnionSet(mod);
3049931278
3050031279 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {
3050131280 err_set_ty = chosen_set_ty;
3050231281 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {
3050331282 err_set_ty = candidate_set_ty;
3050431283 } else {
30505 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_set_ty);
31284 err_set_ty = try sema.errorSetMerge(chosen_set_ty, candidate_set_ty);
3050631285 }
3050731286 continue;
3050831287 }
......@@ -30510,26 +31289,26 @@ fn resolvePeerTypes(
3051031289
3051131290 else => {
3051231291 if (err_set_ty) |chosen_set_ty| {
30513 const candidate_set_ty = candidate_ty.errorUnionSet();
31292 const candidate_set_ty = candidate_ty.errorUnionSet(mod);
3051431293 if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, chosen_set_ty, candidate_set_ty, src, src)) {
3051531294 err_set_ty = chosen_set_ty;
3051631295 } else if (.ok == try sema.coerceInMemoryAllowedErrorSets(block, candidate_set_ty, chosen_set_ty, src, src)) {
3051731296 err_set_ty = null;
3051831297 } else {
30519 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, candidate_set_ty);
31298 err_set_ty = try sema.errorSetMerge(chosen_set_ty, candidate_set_ty);
3052031299 }
3052131300 }
30522 seen_const = seen_const or chosen_ty.isConstPtr();
31301 seen_const = seen_const or chosen_ty.isConstPtr(mod);
3052331302 chosen = candidate;
3052431303 chosen_i = candidate_i + 1;
3052531304 continue;
3052631305 },
3052731306 },
3052831307 .Pointer => {
30529 const cand_info = candidate_ty.ptrInfo().data;
31308 const cand_info = candidate_ty.ptrInfo(mod);
3053031309 switch (chosen_ty_tag) {
3053131310 .Pointer => {
30532 const chosen_info = chosen_ty.ptrInfo().data;
31311 const chosen_info = chosen_ty.ptrInfo(mod);
3053331312
3053431313 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;
3053531314
......@@ -30537,7 +31316,7 @@ fn resolvePeerTypes(
3053731316 // *[N]T to []T
3053831317 if ((cand_info.size == .Many or cand_info.size == .Slice) and
3053931318 chosen_info.size == .One and
30540 chosen_info.pointee_type.zigTypeTag() == .Array)
31319 chosen_info.pointee_type.zigTypeTag(mod) == .Array)
3054131320 {
3054231321 // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T`
3054331322 convert_to_slice = false;
......@@ -30546,7 +31325,7 @@ fn resolvePeerTypes(
3054631325 continue;
3054731326 }
3054831327 if (cand_info.size == .One and
30549 cand_info.pointee_type.zigTypeTag() == .Array and
31328 cand_info.pointee_type.zigTypeTag(mod) == .Array and
3055031329 (chosen_info.size == .Many or chosen_info.size == .Slice))
3055131330 {
3055231331 // In case we see i.e.: `*[1]T`, `*[2]T`, `[*]T`
......@@ -30559,11 +31338,11 @@ fn resolvePeerTypes(
3055931338 // Keep the one whose element type can be coerced into.
3056031339 if (chosen_info.size == .One and
3056131340 cand_info.size == .One and
30562 chosen_info.pointee_type.zigTypeTag() == .Array and
30563 cand_info.pointee_type.zigTypeTag() == .Array)
31341 chosen_info.pointee_type.zigTypeTag(mod) == .Array and
31342 cand_info.pointee_type.zigTypeTag(mod) == .Array)
3056431343 {
30565 const chosen_elem_ty = chosen_info.pointee_type.childType();
30566 const cand_elem_ty = cand_info.pointee_type.childType();
31344 const chosen_elem_ty = chosen_info.pointee_type.childType(mod);
31345 const cand_elem_ty = cand_info.pointee_type.childType(mod);
3056731346
3056831347 const chosen_ok = .ok == try sema.coerceInMemoryAllowed(block, chosen_elem_ty, cand_elem_ty, chosen_info.mutable, target, src, src);
3056931348 if (chosen_ok) {
......@@ -30629,17 +31408,16 @@ fn resolvePeerTypes(
3062931408 }
3063031409 },
3063131410 .Optional => {
30632 var opt_child_buf: Type.Payload.ElemType = undefined;
30633 const chosen_ptr_ty = chosen_ty.optionalChild(&opt_child_buf);
30634 if (chosen_ptr_ty.zigTypeTag() == .Pointer) {
30635 const chosen_info = chosen_ptr_ty.ptrInfo().data;
31411 const chosen_ptr_ty = chosen_ty.optionalChild(mod);
31412 if (chosen_ptr_ty.zigTypeTag(mod) == .Pointer) {
31413 const chosen_info = chosen_ptr_ty.ptrInfo(mod);
3063631414
3063731415 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;
3063831416
3063931417 // *[N]T to ?![*]T
3064031418 // *[N]T to ?![]T
3064131419 if (cand_info.size == .One and
30642 cand_info.pointee_type.zigTypeTag() == .Array and
31420 cand_info.pointee_type.zigTypeTag(mod) == .Array and
3064331421 (chosen_info.size == .Many or chosen_info.size == .Slice))
3064431422 {
3064531423 continue;
......@@ -30647,16 +31425,16 @@ fn resolvePeerTypes(
3064731425 }
3064831426 },
3064931427 .ErrorUnion => {
30650 const chosen_ptr_ty = chosen_ty.errorUnionPayload();
30651 if (chosen_ptr_ty.zigTypeTag() == .Pointer) {
30652 const chosen_info = chosen_ptr_ty.ptrInfo().data;
31428 const chosen_ptr_ty = chosen_ty.errorUnionPayload(mod);
31429 if (chosen_ptr_ty.zigTypeTag(mod) == .Pointer) {
31430 const chosen_info = chosen_ptr_ty.ptrInfo(mod);
3065331431
3065431432 seen_const = seen_const or !chosen_info.mutable or !cand_info.mutable;
3065531433
3065631434 // *[N]T to E![*]T
3065731435 // *[N]T to E![]T
3065831436 if (cand_info.size == .One and
30659 cand_info.pointee_type.zigTypeTag() == .Array and
31437 cand_info.pointee_type.zigTypeTag(mod) == .Array and
3066031438 (chosen_info.size == .Many or chosen_info.size == .Slice))
3066131439 {
3066231440 continue;
......@@ -30664,7 +31442,7 @@ fn resolvePeerTypes(
3066431442 }
3066531443 },
3066631444 .Fn => {
30667 if (!cand_info.mutable and cand_info.pointee_type.zigTypeTag() == .Fn and .ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty, cand_info.pointee_type, target, src, src)) {
31445 if (!cand_info.mutable and cand_info.pointee_type.zigTypeTag(mod) == .Fn and .ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty, cand_info.pointee_type, target, src, src)) {
3066831446 chosen = candidate;
3066931447 chosen_i = candidate_i + 1;
3067031448 continue;
......@@ -30674,15 +31452,14 @@ fn resolvePeerTypes(
3067431452 }
3067531453 },
3067631454 .Optional => {
30677 var opt_child_buf: Type.Payload.ElemType = undefined;
30678 const opt_child_ty = candidate_ty.optionalChild(&opt_child_buf);
31455 const opt_child_ty = candidate_ty.optionalChild(mod);
3067931456 if ((try sema.coerceInMemoryAllowed(block, chosen_ty, opt_child_ty, false, target, src, src)) == .ok) {
30680 seen_const = seen_const or opt_child_ty.isConstPtr();
31457 seen_const = seen_const or opt_child_ty.isConstPtr(mod);
3068131458 any_are_null = true;
3068231459 continue;
3068331460 }
3068431461
30685 seen_const = seen_const or chosen_ty.isConstPtr();
31462 seen_const = seen_const or chosen_ty.isConstPtr(mod);
3068631463 any_are_null = false;
3068731464 chosen = candidate;
3068831465 chosen_i = candidate_i + 1;
......@@ -30690,23 +31467,23 @@ fn resolvePeerTypes(
3069031467 },
3069131468 .Vector => switch (chosen_ty_tag) {
3069231469 .Vector => {
30693 const chosen_len = chosen_ty.vectorLen();
30694 const candidate_len = candidate_ty.vectorLen();
31470 const chosen_len = chosen_ty.vectorLen(mod);
31471 const candidate_len = candidate_ty.vectorLen(mod);
3069531472 if (chosen_len != candidate_len)
3069631473 continue;
3069731474
30698 const chosen_child_ty = chosen_ty.childType();
30699 const candidate_child_ty = candidate_ty.childType();
30700 if (chosen_child_ty.zigTypeTag() == .Int and candidate_child_ty.zigTypeTag() == .Int) {
30701 const chosen_info = chosen_child_ty.intInfo(target);
30702 const candidate_info = candidate_child_ty.intInfo(target);
31475 const chosen_child_ty = chosen_ty.childType(mod);
31476 const candidate_child_ty = candidate_ty.childType(mod);
31477 if (chosen_child_ty.zigTypeTag(mod) == .Int and candidate_child_ty.zigTypeTag(mod) == .Int) {
31478 const chosen_info = chosen_child_ty.intInfo(mod);
31479 const candidate_info = candidate_child_ty.intInfo(mod);
3070331480 if (chosen_info.bits < candidate_info.bits) {
3070431481 chosen = candidate;
3070531482 chosen_i = candidate_i + 1;
3070631483 }
3070731484 continue;
3070831485 }
30709 if (chosen_child_ty.zigTypeTag() == .Float and candidate_child_ty.zigTypeTag() == .Float) {
31486 if (chosen_child_ty.zigTypeTag(mod) == .Float and candidate_child_ty.zigTypeTag(mod) == .Float) {
3071031487 if (chosen_ty.floatBits(target) < candidate_ty.floatBits(target)) {
3071131488 chosen = candidate;
3071231489 chosen_i = candidate_i + 1;
......@@ -30725,8 +31502,8 @@ fn resolvePeerTypes(
3072531502 .Vector => continue,
3072631503 else => {},
3072731504 },
30728 .Fn => if (chosen_ty.isSinglePointer() and chosen_ty.isConstPtr() and chosen_ty.childType().zigTypeTag() == .Fn) {
30729 if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(), candidate_ty, target, src, src)) {
31505 .Fn => if (chosen_ty.isSinglePointer(mod) and chosen_ty.isConstPtr(mod) and chosen_ty.childType(mod).zigTypeTag(mod) == .Fn) {
31506 if (.ok == try sema.coerceInMemoryAllowedFns(block, chosen_ty.childType(mod), candidate_ty, target, src, src)) {
3073031507 continue;
3073131508 }
3073231509 },
......@@ -30746,8 +31523,7 @@ fn resolvePeerTypes(
3074631523 continue;
3074731524 },
3074831525 .Optional => {
30749 var opt_child_buf: Type.Payload.ElemType = undefined;
30750 const opt_child_ty = chosen_ty.optionalChild(&opt_child_buf);
31526 const opt_child_ty = chosen_ty.optionalChild(mod);
3075131527 if ((try sema.coerceInMemoryAllowed(block, opt_child_ty, candidate_ty, false, target, src, src)) == .ok) {
3075231528 continue;
3075331529 }
......@@ -30759,7 +31535,7 @@ fn resolvePeerTypes(
3075931535 }
3076031536 },
3076131537 .ErrorUnion => {
30762 const payload_ty = chosen_ty.errorUnionPayload();
31538 const payload_ty = chosen_ty.errorUnionPayload(mod);
3076331539 if ((try sema.coerceInMemoryAllowed(block, payload_ty, candidate_ty, false, target, src, src)) == .ok) {
3076431540 continue;
3076531541 }
......@@ -30776,7 +31552,7 @@ fn resolvePeerTypes(
3077631552 continue;
3077731553 }
3077831554
30779 err_set_ty = try chosen_set_ty.errorSetMerge(sema.arena, chosen_ty);
31555 err_set_ty = try sema.errorSetMerge(chosen_set_ty, chosen_ty);
3078031556 continue;
3078131557 } else {
3078231558 err_set_ty = chosen_ty;
......@@ -30789,28 +31565,28 @@ fn resolvePeerTypes(
3078931565 // At this point, we hit a compile error. We need to recover
3079031566 // the source locations.
3079131567 const chosen_src = candidate_srcs.resolve(
30792 sema.gpa,
30793 sema.mod.declPtr(block.src_decl),
31568 mod,
31569 mod.declPtr(block.src_decl),
3079431570 chosen_i,
3079531571 );
3079631572 const candidate_src = candidate_srcs.resolve(
30797 sema.gpa,
30798 sema.mod.declPtr(block.src_decl),
31573 mod,
31574 mod.declPtr(block.src_decl),
3079931575 candidate_i + 1,
3080031576 );
3080131577
3080231578 const msg = msg: {
3080331579 const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{
30804 chosen_ty.fmt(sema.mod),
30805 candidate_ty.fmt(sema.mod),
31580 chosen_ty.fmt(mod),
31581 candidate_ty.fmt(mod),
3080631582 });
3080731583 errdefer msg.destroy(sema.gpa);
3080831584
3080931585 if (chosen_src) |src_loc|
30810 try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty.fmt(sema.mod)});
31586 try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty.fmt(mod)});
3081131587
3081231588 if (candidate_src) |src_loc|
30813 try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty.fmt(sema.mod)});
31589 try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty.fmt(mod)});
3081431590
3081531591 break :msg msg;
3081631592 };
......@@ -30821,139 +31597,231 @@ fn resolvePeerTypes(
3082131597
3082231598 if (convert_to_slice) {
3082331599 // turn *[N]T => []T
30824 const chosen_child_ty = chosen_ty.childType();
30825 var info = chosen_ty.ptrInfo();
30826 info.data.sentinel = chosen_child_ty.sentinel();
30827 info.data.size = .Slice;
30828 info.data.mutable = !(seen_const or chosen_child_ty.isConstPtr());
30829 info.data.pointee_type = chosen_child_ty.elemType2();
30830
30831 const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);
31600 const chosen_child_ty = chosen_ty.childType(mod);
31601 var info = chosen_ty.ptrInfo(mod);
31602 info.sentinel = chosen_child_ty.sentinel(mod);
31603 info.size = .Slice;
31604 info.mutable = !(seen_const or chosen_child_ty.isConstPtr(mod));
31605 info.pointee_type = chosen_child_ty.elemType2(mod);
31606
31607 const new_ptr_ty = try Type.ptr(sema.arena, mod, info);
3083231608 const opt_ptr_ty = if (any_are_null)
30833 try Type.optional(sema.arena, new_ptr_ty)
31609 try Type.optional(sema.arena, new_ptr_ty, mod)
3083431610 else
3083531611 new_ptr_ty;
3083631612 const set_ty = err_set_ty orelse return opt_ptr_ty;
30837 return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod);
31613 return try mod.errorUnionType(set_ty, opt_ptr_ty);
3083831614 }
3083931615
3084031616 if (seen_const) {
3084131617 // turn []T => []const T
30842 switch (chosen_ty.zigTypeTag()) {
31618 switch (chosen_ty.zigTypeTag(mod)) {
3084331619 .ErrorUnion => {
30844 const ptr_ty = chosen_ty.errorUnionPayload();
30845 var info = ptr_ty.ptrInfo();
30846 info.data.mutable = false;
30847 const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);
31620 const ptr_ty = chosen_ty.errorUnionPayload(mod);
31621 var info = ptr_ty.ptrInfo(mod);
31622 info.mutable = false;
31623 const new_ptr_ty = try Type.ptr(sema.arena, mod, info);
3084831624 const opt_ptr_ty = if (any_are_null)
30849 try Type.optional(sema.arena, new_ptr_ty)
31625 try Type.optional(sema.arena, new_ptr_ty, mod)
3085031626 else
3085131627 new_ptr_ty;
30852 const set_ty = err_set_ty orelse chosen_ty.errorUnionSet();
30853 return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod);
31628 const set_ty = err_set_ty orelse chosen_ty.errorUnionSet(mod);
31629 return try mod.errorUnionType(set_ty, opt_ptr_ty);
3085431630 },
3085531631 .Pointer => {
30856 var info = chosen_ty.ptrInfo();
30857 info.data.mutable = false;
30858 const new_ptr_ty = try Type.ptr(sema.arena, sema.mod, info.data);
31632 var info = chosen_ty.ptrInfo(mod);
31633 info.mutable = false;
31634 const new_ptr_ty = try Type.ptr(sema.arena, mod, info);
3085931635 const opt_ptr_ty = if (any_are_null)
30860 try Type.optional(sema.arena, new_ptr_ty)
31636 try Type.optional(sema.arena, new_ptr_ty, mod)
3086131637 else
3086231638 new_ptr_ty;
3086331639 const set_ty = err_set_ty orelse return opt_ptr_ty;
30864 return try Type.errorUnion(sema.arena, set_ty, opt_ptr_ty, sema.mod);
31640 return try mod.errorUnionType(set_ty, opt_ptr_ty);
3086531641 },
3086631642 else => return chosen_ty,
3086731643 }
3086831644 }
3086931645
3087031646 if (any_are_null) {
30871 const opt_ty = switch (chosen_ty.zigTypeTag()) {
31647 const opt_ty = switch (chosen_ty.zigTypeTag(mod)) {
3087231648 .Null, .Optional => chosen_ty,
30873 else => try Type.optional(sema.arena, chosen_ty),
31649 else => try Type.optional(sema.arena, chosen_ty, mod),
3087431650 };
3087531651 const set_ty = err_set_ty orelse return opt_ty;
30876 return try Type.errorUnion(sema.arena, set_ty, opt_ty, sema.mod);
31652 return try mod.errorUnionType(set_ty, opt_ty);
3087731653 }
3087831654
30879 if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag()) {
31655 if (err_set_ty) |ty| switch (chosen_ty.zigTypeTag(mod)) {
3088031656 .ErrorSet => return ty,
3088131657 .ErrorUnion => {
30882 const payload_ty = chosen_ty.errorUnionPayload();
30883 return try Type.errorUnion(sema.arena, ty, payload_ty, sema.mod);
31658 const payload_ty = chosen_ty.errorUnionPayload(mod);
31659 return try mod.errorUnionType(ty, payload_ty);
3088431660 },
30885 else => return try Type.errorUnion(sema.arena, ty, chosen_ty, sema.mod),
31661 else => return try mod.errorUnionType(ty, chosen_ty),
3088631662 };
3088731663
3088831664 return chosen_ty;
3088931665}
3089031666
30891pub fn resolveFnTypes(sema: *Sema, fn_info: Type.Payload.Function.Data) CompileError!void {
30892 try sema.resolveTypeFully(fn_info.return_type);
31667pub fn resolveFnTypes(sema: *Sema, fn_ty: Type) CompileError!void {
31668 const mod = sema.mod;
31669 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.return_type.toType());
3089331670
30894 if (sema.mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.isError()) {
31671 if (mod.comp.bin_file.options.error_return_tracing and mod.typeToFunc(fn_ty).?.return_type.toType().isError(mod)) {
3089531672 // Ensure the type exists so that backends can assume that.
3089631673 _ = try sema.getBuiltinType("StackTrace");
3089731674 }
3089831675
30899 for (fn_info.param_types) |param_ty| {
30900 try sema.resolveTypeFully(param_ty);
31676 for (0..mod.typeToFunc(fn_ty).?.param_types.len) |i| {
31677 try sema.resolveTypeFully(mod.typeToFunc(fn_ty).?.param_types[i].toType());
3090131678 }
3090231679}
3090331680
3090431681/// Make it so that calling hash() and eql() on `val` will not assert due
3090531682/// to a type not having its layout resolved.
30906fn resolveLazyValue(sema: *Sema, val: Value) CompileError!void {
30907 switch (val.tag()) {
30908 .lazy_align => {
30909 const ty = val.castTag(.lazy_align).?.data;
30910 return sema.resolveTypeLayout(ty);
30911 },
30912 .lazy_size => {
30913 const ty = val.castTag(.lazy_size).?.data;
30914 return sema.resolveTypeLayout(ty);
30915 },
30916 .comptime_field_ptr => {
30917 const field_ptr = val.castTag(.comptime_field_ptr).?.data;
30918 return sema.resolveLazyValue(field_ptr.field_val);
30919 },
30920 .eu_payload,
30921 .opt_payload,
30922 => {
30923 const sub_val = val.cast(Value.Payload.SubValue).?.data;
30924 return sema.resolveLazyValue(sub_val);
30925 },
30926 .@"union" => {
30927 const union_val = val.castTag(.@"union").?.data;
30928 return sema.resolveLazyValue(union_val.val);
30929 },
30930 .aggregate => {
30931 const aggregate = val.castTag(.aggregate).?.data;
30932 for (aggregate) |elem_val| {
30933 try sema.resolveLazyValue(elem_val);
31683fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
31684 const mod = sema.mod;
31685 switch (mod.intern_pool.indexToKey(val.toIntern())) {
31686 .int => |int| switch (int.storage) {
31687 .u64, .i64, .big_int => return val,
31688 .lazy_align, .lazy_size => return (try mod.intern(.{ .int = .{
31689 .ty = int.ty,
31690 .storage = .{ .u64 = (try val.getUnsignedIntAdvanced(mod, sema)).? },
31691 } })).toValue(),
31692 },
31693 .ptr => |ptr| {
31694 const resolved_len = switch (ptr.len) {
31695 .none => .none,
31696 else => (try sema.resolveLazyValue(ptr.len.toValue())).toIntern(),
31697 };
31698 switch (ptr.addr) {
31699 .decl, .mut_decl => return if (resolved_len == ptr.len)
31700 val
31701 else
31702 (try mod.intern(.{ .ptr = .{
31703 .ty = ptr.ty,
31704 .addr = switch (ptr.addr) {
31705 .decl => |decl| .{ .decl = decl },
31706 .mut_decl => |mut_decl| .{ .mut_decl = mut_decl },
31707 else => unreachable,
31708 },
31709 .len = resolved_len,
31710 } })).toValue(),
31711 .comptime_field => |field_val| {
31712 const resolved_field_val =
31713 (try sema.resolveLazyValue(field_val.toValue())).toIntern();
31714 return if (resolved_field_val == field_val and resolved_len == ptr.len)
31715 val
31716 else
31717 (try mod.intern(.{ .ptr = .{
31718 .ty = ptr.ty,
31719 .addr = .{ .comptime_field = resolved_field_val },
31720 .len = resolved_len,
31721 } })).toValue();
31722 },
31723 .int => |int| {
31724 const resolved_int = (try sema.resolveLazyValue(int.toValue())).toIntern();
31725 return if (resolved_int == int and resolved_len == ptr.len)
31726 val
31727 else
31728 (try mod.intern(.{ .ptr = .{
31729 .ty = ptr.ty,
31730 .addr = .{ .int = resolved_int },
31731 .len = resolved_len,
31732 } })).toValue();
31733 },
31734 .eu_payload, .opt_payload => |base| {
31735 const resolved_base = (try sema.resolveLazyValue(base.toValue())).toIntern();
31736 return if (resolved_base == base and resolved_len == ptr.len)
31737 val
31738 else
31739 (try mod.intern(.{ .ptr = .{
31740 .ty = ptr.ty,
31741 .addr = switch (ptr.addr) {
31742 .eu_payload => .{ .eu_payload = resolved_base },
31743 .opt_payload => .{ .opt_payload = resolved_base },
31744 else => unreachable,
31745 },
31746 .len = ptr.len,
31747 } })).toValue();
31748 },
31749 .elem, .field => |base_index| {
31750 const resolved_base = (try sema.resolveLazyValue(base_index.base.toValue())).toIntern();
31751 return if (resolved_base == base_index.base and resolved_len == ptr.len)
31752 val
31753 else
31754 (try mod.intern(.{ .ptr = .{
31755 .ty = ptr.ty,
31756 .addr = switch (ptr.addr) {
31757 .elem => .{ .elem = .{
31758 .base = resolved_base,
31759 .index = base_index.index,
31760 } },
31761 .field => .{ .field = .{
31762 .base = resolved_base,
31763 .index = base_index.index,
31764 } },
31765 else => unreachable,
31766 },
31767 .len = ptr.len,
31768 } })).toValue();
31769 },
3093431770 }
3093531771 },
30936 .slice => {
30937 const slice = val.castTag(.slice).?.data;
30938 try sema.resolveLazyValue(slice.ptr);
30939 return sema.resolveLazyValue(slice.len);
31772 .aggregate => |aggregate| switch (aggregate.storage) {
31773 .bytes => return val,
31774 .elems => |elems| {
31775 var resolved_elems: []InternPool.Index = &.{};
31776 for (elems, 0..) |elem, i| {
31777 const resolved_elem = (try sema.resolveLazyValue(elem.toValue())).toIntern();
31778 if (resolved_elems.len == 0 and resolved_elem != elem) {
31779 resolved_elems = try sema.arena.alloc(InternPool.Index, elems.len);
31780 @memcpy(resolved_elems[0..i], elems[0..i]);
31781 }
31782 if (resolved_elems.len > 0) resolved_elems[i] = resolved_elem;
31783 }
31784 return if (resolved_elems.len == 0) val else (try mod.intern(.{ .aggregate = .{
31785 .ty = aggregate.ty,
31786 .storage = .{ .elems = resolved_elems },
31787 } })).toValue();
31788 },
31789 .repeated_elem => |elem| {
31790 const resolved_elem = (try sema.resolveLazyValue(elem.toValue())).toIntern();
31791 return if (resolved_elem == elem) val else (try mod.intern(.{ .aggregate = .{
31792 .ty = aggregate.ty,
31793 .storage = .{ .repeated_elem = resolved_elem },
31794 } })).toValue();
31795 },
31796 },
31797 .un => |un| {
31798 const resolved_tag = (try sema.resolveLazyValue(un.tag.toValue())).toIntern();
31799 const resolved_val = (try sema.resolveLazyValue(un.val.toValue())).toIntern();
31800 return if (resolved_tag == un.tag and resolved_val == un.val)
31801 val
31802 else
31803 (try mod.intern(.{ .un = .{
31804 .ty = un.ty,
31805 .tag = resolved_tag,
31806 .val = resolved_val,
31807 } })).toValue();
3094031808 },
30941 else => return,
31809 else => return val,
3094231810 }
3094331811}
3094431812
3094531813pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
30946 switch (ty.zigTypeTag()) {
31814 const mod = sema.mod;
31815 switch (ty.zigTypeTag(mod)) {
3094731816 .Struct => return sema.resolveStructLayout(ty),
3094831817 .Union => return sema.resolveUnionLayout(ty),
3094931818 .Array => {
30950 if (ty.arrayLenIncludingSentinel() == 0) return;
30951 const elem_ty = ty.childType();
31819 if (ty.arrayLenIncludingSentinel(mod) == 0) return;
31820 const elem_ty = ty.childType(mod);
3095231821 return sema.resolveTypeLayout(elem_ty);
3095331822 },
3095431823 .Optional => {
30955 var buf: Type.Payload.ElemType = undefined;
30956 const payload_ty = ty.optionalChild(&buf);
31824 const payload_ty = ty.optionalChild(mod);
3095731825 // In case of querying the ABI alignment of this optional, we will ask
3095831826 // for hasRuntimeBits() of the payload type, so we need "requires comptime"
3095931827 // to be known already before this function returns.
......@@ -30961,37 +31829,37 @@ pub fn resolveTypeLayout(sema: *Sema, ty: Type) CompileError!void {
3096131829 return sema.resolveTypeLayout(payload_ty);
3096231830 },
3096331831 .ErrorUnion => {
30964 const payload_ty = ty.errorUnionPayload();
31832 const payload_ty = ty.errorUnionPayload(mod);
3096531833 return sema.resolveTypeLayout(payload_ty);
3096631834 },
3096731835 .Fn => {
30968 const info = ty.fnInfo();
31836 const info = mod.typeToFunc(ty).?;
3096931837 if (info.is_generic) {
3097031838 // Resolving of generic function types is deferred to when
3097131839 // the function is instantiated.
3097231840 return;
3097331841 }
3097431842 for (info.param_types) |param_ty| {
30975 try sema.resolveTypeLayout(param_ty);
31843 try sema.resolveTypeLayout(param_ty.toType());
3097631844 }
30977 try sema.resolveTypeLayout(info.return_type);
31845 try sema.resolveTypeLayout(info.return_type.toType());
3097831846 },
3097931847 else => {},
3098031848 }
3098131849}
3098231850
3098331851fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
31852 const mod = sema.mod;
3098431853 const resolved_ty = try sema.resolveTypeFields(ty);
30985 if (resolved_ty.castTag(.@"struct")) |payload| {
30986 const struct_obj = payload.data;
31854 if (mod.typeToStruct(resolved_ty)) |struct_obj| {
3098731855 switch (struct_obj.status) {
3098831856 .none, .have_field_types => {},
3098931857 .field_types_wip, .layout_wip => {
3099031858 const msg = try Module.ErrorMsg.create(
3099131859 sema.gpa,
30992 struct_obj.srcLoc(sema.mod),
31860 struct_obj.srcLoc(mod),
3099331861 "struct '{}' depends on itself",
30994 .{ty.fmt(sema.mod)},
31862 .{ty.fmt(mod)},
3099531863 );
3099631864 return sema.failWithOwnedErrorMsg(msg);
3099731865 },
......@@ -31015,35 +31883,27 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3101531883 }
3101631884
3101731885 if (struct_obj.layout == .Packed) {
31018 try semaBackingIntType(sema.mod, struct_obj);
31886 try semaBackingIntType(mod, struct_obj);
3101931887 }
3102031888
3102131889 struct_obj.status = .have_layout;
3102231890 _ = try sema.resolveTypeRequiresComptime(resolved_ty);
3102331891
31024 if (struct_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
31892 if (struct_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {
3102531893 const msg = try Module.ErrorMsg.create(
3102631894 sema.gpa,
31027 struct_obj.srcLoc(sema.mod),
31895 struct_obj.srcLoc(mod),
3102831896 "struct layout depends on it having runtime bits",
3102931897 .{},
3103031898 );
3103131899 return sema.failWithOwnedErrorMsg(msg);
3103231900 }
3103331901
31034 if (struct_obj.layout == .Auto and sema.mod.backendSupportsFeature(.field_reordering)) {
31035 const optimized_order = if (struct_obj.owner_decl == sema.owner_decl_index)
31036 try sema.perm_arena.alloc(u32, struct_obj.fields.count())
31037 else blk: {
31038 const decl = sema.mod.declPtr(struct_obj.owner_decl);
31039 var decl_arena: std.heap.ArenaAllocator = undefined;
31040 const decl_arena_allocator = decl.value_arena.?.acquire(sema.mod.gpa, &decl_arena);
31041 defer decl.value_arena.?.release(&decl_arena);
31042 break :blk try decl_arena_allocator.alloc(u32, struct_obj.fields.count());
31043 };
31902 if (struct_obj.layout == .Auto and mod.backendSupportsFeature(.field_reordering)) {
31903 const optimized_order = try mod.tmp_hack_arena.allocator().alloc(u32, struct_obj.fields.count());
3104431904
3104531905 for (struct_obj.fields.values(), 0..) |field, i| {
31046 optimized_order[i] = if (field.ty.hasRuntimeBits())
31906 optimized_order[i] = if (try sema.typeHasRuntimeBits(field.ty))
3104731907 @intCast(u32, i)
3104831908 else
3104931909 Module.Struct.omitted_field;
......@@ -31054,11 +31914,11 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3105431914 sema: *Sema,
3105531915
3105631916 fn lessThan(ctx: @This(), a: u32, b: u32) bool {
31917 const m = ctx.sema.mod;
3105731918 if (a == Module.Struct.omitted_field) return false;
3105831919 if (b == Module.Struct.omitted_field) return true;
31059 const target = ctx.sema.mod.getTarget();
31060 return ctx.struct_obj.fields.values()[a].ty.abiAlignment(target) >
31061 ctx.struct_obj.fields.values()[b].ty.abiAlignment(target);
31920 return ctx.struct_obj.fields.values()[a].ty.abiAlignment(m) >
31921 ctx.struct_obj.fields.values()[b].ty.abiAlignment(m);
3106231922 }
3106331923 };
3106431924 mem.sort(u32, optimized_order, AlignSortContext{
......@@ -31073,20 +31933,16 @@ fn resolveStructLayout(sema: *Sema, ty: Type) CompileError!void {
3107331933
3107431934fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!void {
3107531935 const gpa = mod.gpa;
31076 const target = mod.getTarget();
3107731936
3107831937 var fields_bit_sum: u64 = 0;
3107931938 for (struct_obj.fields.values()) |field| {
31080 fields_bit_sum += field.ty.bitSize(target);
31939 fields_bit_sum += field.ty.bitSize(mod);
3108131940 }
3108231941
3108331942 const decl_index = struct_obj.owner_decl;
3108431943 const decl = mod.declPtr(decl_index);
31085 var decl_arena: std.heap.ArenaAllocator = undefined;
31086 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
31087 defer decl.value_arena.?.release(&decl_arena);
3108831944
31089 const zir = struct_obj.namespace.file_scope.zir;
31945 const zir = mod.namespacePtr(struct_obj.namespace).file_scope.zir;
3109031946 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
3109131947 assert(extended.opcode == .struct_decl);
3109231948 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -31103,28 +31959,33 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3110331959 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3110431960 defer analysis_arena.deinit();
3110531961
31962 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
31963 defer comptime_mutable_decls.deinit();
31964
3110631965 var sema: Sema = .{
3110731966 .mod = mod,
3110831967 .gpa = gpa,
3110931968 .arena = analysis_arena.allocator(),
31110 .perm_arena = decl_arena_allocator,
3111131969 .code = zir,
3111231970 .owner_decl = decl,
3111331971 .owner_decl_index = decl_index,
3111431972 .func = null,
31973 .func_index = .none,
3111531974 .fn_ret_ty = Type.void,
3111631975 .owner_func = null,
31976 .owner_func_index = .none,
31977 .comptime_mutable_decls = &comptime_mutable_decls,
3111731978 };
3111831979 defer sema.deinit();
3111931980
31120 var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
31981 var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope);
3112131982 defer wip_captures.deinit();
3112231983
3112331984 var block: Block = .{
3112431985 .parent = null,
3112531986 .sema = &sema,
3112631987 .src_decl = decl_index,
31127 .namespace = &struct_obj.namespace,
31988 .namespace = struct_obj.namespace,
3112831989 .wip_capture_scope = wip_captures.scope,
3112931990 .instructions = .{},
3113031991 .inlining = null,
......@@ -31148,21 +32009,27 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3114832009 };
3114932010
3115032011 try sema.checkBackingIntType(&block, backing_int_src, backing_int_ty, fields_bit_sum);
31151 struct_obj.backing_int_ty = try backing_int_ty.copy(decl_arena_allocator);
32012 struct_obj.backing_int_ty = backing_int_ty;
3115232013 try wip_captures.finalize();
32014 for (comptime_mutable_decls.items) |ct_decl_index| {
32015 const ct_decl = mod.declPtr(ct_decl_index);
32016 try ct_decl.intern(mod);
32017 }
3115332018 } else {
3115432019 if (fields_bit_sum > std.math.maxInt(u16)) {
3115532020 var sema: Sema = .{
3115632021 .mod = mod,
3115732022 .gpa = gpa,
3115832023 .arena = undefined,
31159 .perm_arena = decl_arena_allocator,
3116032024 .code = zir,
3116132025 .owner_decl = decl,
3116232026 .owner_decl_index = decl_index,
3116332027 .func = null,
32028 .func_index = .none,
3116432029 .fn_ret_ty = Type.void,
3116532030 .owner_func = null,
32031 .owner_func_index = .none,
32032 .comptime_mutable_decls = undefined,
3116632033 };
3116732034 defer sema.deinit();
3116832035
......@@ -31170,7 +32037,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3117032037 .parent = null,
3117132038 .sema = &sema,
3117232039 .src_decl = decl_index,
31173 .namespace = &struct_obj.namespace,
32040 .namespace = struct_obj.namespace,
3117432041 .wip_capture_scope = undefined,
3117532042 .instructions = .{},
3117632043 .inlining = null,
......@@ -31178,32 +32045,29 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3117832045 };
3117932046 return sema.fail(&block, LazySrcLoc.nodeOffset(0), "size of packed struct '{d}' exceeds maximum bit width of 65535", .{fields_bit_sum});
3118032047 }
31181 var buf: Type.Payload.Bits = .{
31182 .base = .{ .tag = .int_unsigned },
31183 .data = @intCast(u16, fields_bit_sum),
31184 };
31185 struct_obj.backing_int_ty = try Type.initPayload(&buf.base).copy(decl_arena_allocator);
32048 struct_obj.backing_int_ty = try mod.intType(.unsigned, @intCast(u16, fields_bit_sum));
3118632049 }
3118732050}
3118832051
3118932052fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void {
31190 const target = sema.mod.getTarget();
32053 const mod = sema.mod;
3119132054
31192 if (!backing_int_ty.isInt()) {
32055 if (!backing_int_ty.isInt(mod)) {
3119332056 return sema.fail(block, src, "expected backing integer type, found '{}'", .{backing_int_ty.fmt(sema.mod)});
3119432057 }
31195 if (backing_int_ty.bitSize(target) != fields_bit_sum) {
32058 if (backing_int_ty.bitSize(mod) != fields_bit_sum) {
3119632059 return sema.fail(
3119732060 block,
3119832061 src,
3119932062 "backing integer type '{}' has bit size {} but the struct fields have a total bit size of {}",
31200 .{ backing_int_ty.fmt(sema.mod), backing_int_ty.bitSize(target), fields_bit_sum },
32063 .{ backing_int_ty.fmt(sema.mod), backing_int_ty.bitSize(mod), fields_bit_sum },
3120132064 );
3120232065 }
3120332066}
3120432067
3120532068fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31206 if (!ty.isIndexable()) {
32069 const mod = sema.mod;
32070 if (!ty.isIndexable(mod)) {
3120732071 const msg = msg: {
3120832072 const msg = try sema.errMsg(block, src, "type '{}' does not support indexing", .{ty.fmt(sema.mod)});
3120932073 errdefer msg.destroy(sema.gpa);
......@@ -31215,12 +32079,13 @@ fn checkIndexable(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
3121532079}
3121632080
3121732081fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void {
31218 if (ty.zigTypeTag() == .Pointer) {
31219 switch (ty.ptrSize()) {
32082 const mod = sema.mod;
32083 if (ty.zigTypeTag(mod) == .Pointer) {
32084 switch (ty.ptrSize(mod)) {
3122032085 .Slice, .Many, .C => return,
3122132086 .One => {
31222 const elem_ty = ty.childType();
31223 if (elem_ty.zigTypeTag() == .Array) return;
32087 const elem_ty = ty.childType(mod);
32088 if (elem_ty.zigTypeTag(mod) == .Array) return;
3122432089 // TODO https://github.com/ziglang/zig/issues/15479
3122532090 // if (elem_ty.isTuple()) return;
3122632091 },
......@@ -31236,8 +32101,9 @@ fn checkMemOperand(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) !void
3123632101}
3123732102
3123832103fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
32104 const mod = sema.mod;
3123932105 const resolved_ty = try sema.resolveTypeFields(ty);
31240 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
32106 const union_obj = mod.typeToUnion(resolved_ty).?;
3124132107 switch (union_obj.status) {
3124232108 .none, .have_field_types => {},
3124332109 .field_types_wip, .layout_wip => {
......@@ -31270,7 +32136,7 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3127032136 union_obj.status = .have_layout;
3127132137 _ = try sema.resolveTypeRequiresComptime(resolved_ty);
3127232138
31273 if (union_obj.assumed_runtime_bits and !resolved_ty.hasRuntimeBits()) {
32139 if (union_obj.assumed_runtime_bits and !(try sema.typeHasRuntimeBits(resolved_ty))) {
3127432140 const msg = try Module.ErrorMsg.create(
3127532141 sema.gpa,
3127632142 union_obj.srcLoc(sema.mod),
......@@ -31285,188 +32151,154 @@ fn resolveUnionLayout(sema: *Sema, ty: Type) CompileError!void {
3128532151// for hasRuntimeBits() of each field, so we need "requires comptime"
3128632152// to be known already before this function returns.
3128732153pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
31288 return switch (ty.tag()) {
31289 .u1,
31290 .u8,
31291 .i8,
31292 .u16,
31293 .i16,
31294 .u29,
31295 .u32,
31296 .i32,
31297 .u64,
31298 .i64,
31299 .u128,
31300 .i128,
31301 .usize,
31302 .isize,
31303 .c_char,
31304 .c_short,
31305 .c_ushort,
31306 .c_int,
31307 .c_uint,
31308 .c_long,
31309 .c_ulong,
31310 .c_longlong,
31311 .c_ulonglong,
31312 .c_longdouble,
31313 .f16,
31314 .f32,
31315 .f64,
31316 .f80,
31317 .f128,
31318 .anyopaque,
31319 .bool,
31320 .void,
31321 .anyerror,
31322 .noreturn,
31323 .@"anyframe",
31324 .null,
31325 .undefined,
31326 .atomic_order,
31327 .atomic_rmw_op,
31328 .calling_convention,
31329 .address_space,
31330 .float_mode,
31331 .reduce_op,
31332 .modifier,
31333 .prefetch_options,
31334 .export_options,
31335 .extern_options,
31336 .manyptr_u8,
31337 .manyptr_const_u8,
31338 .manyptr_const_u8_sentinel_0,
31339 .const_slice_u8,
31340 .const_slice_u8_sentinel_0,
31341 .anyerror_void_error_union,
31342 .empty_struct_literal,
31343 .empty_struct,
31344 .error_set,
31345 .error_set_single,
31346 .error_set_inferred,
31347 .error_set_merged,
31348 .@"opaque",
31349 .generic_poison,
31350 .array_u8,
31351 .array_u8_sentinel_0,
31352 .int_signed,
31353 .int_unsigned,
31354 .enum_simple,
31355 => false,
31356
31357 .single_const_pointer_to_comptime_int,
31358 .type,
31359 .comptime_int,
31360 .comptime_float,
31361 .enum_literal,
31362 .type_info,
31363 // These are function bodies, not function pointers.
31364 .fn_noreturn_no_args,
31365 .fn_void_no_args,
31366 .fn_naked_noreturn_no_args,
31367 .fn_ccc_void_no_args,
31368 .function,
31369 => true,
31370
31371 .inferred_alloc_mut => unreachable,
31372 .inferred_alloc_const => unreachable,
31373
31374 .array,
31375 .array_sentinel,
31376 .vector,
31377 => return sema.resolveTypeRequiresComptime(ty.childType()),
31378
31379 .pointer,
31380 .single_const_pointer,
31381 .single_mut_pointer,
31382 .many_const_pointer,
31383 .many_mut_pointer,
31384 .c_const_pointer,
31385 .c_mut_pointer,
31386 .const_slice,
31387 .mut_slice,
31388 => {
31389 const child_ty = ty.childType();
31390 if (child_ty.zigTypeTag() == .Fn) {
31391 return child_ty.fnInfo().is_generic;
31392 } else {
31393 return sema.resolveTypeRequiresComptime(child_ty);
31394 }
31395 },
31396
31397 .optional,
31398 .optional_single_mut_pointer,
31399 .optional_single_const_pointer,
31400 => {
31401 var buf: Type.Payload.ElemType = undefined;
31402 return sema.resolveTypeRequiresComptime(ty.optionalChild(&buf));
31403 },
32154 const mod = sema.mod;
3140432155
31405 .tuple, .anon_struct => {
31406 const tuple = ty.tupleFields();
31407 for (tuple.types, 0..) |field_ty, i| {
31408 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
31409 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty)) {
31410 return true;
32156 return switch (ty.toIntern()) {
32157 .empty_struct_type => false,
32158 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
32159 .int_type => false,
32160 .ptr_type => |ptr_type| {
32161 const child_ty = ptr_type.child.toType();
32162 if (child_ty.zigTypeTag(mod) == .Fn) {
32163 return mod.typeToFunc(child_ty).?.is_generic;
32164 } else {
32165 return sema.resolveTypeRequiresComptime(child_ty);
3141132166 }
31412 }
31413 return false;
31414 },
32167 },
32168 .anyframe_type => |child| {
32169 if (child == .none) return false;
32170 return sema.resolveTypeRequiresComptime(child.toType());
32171 },
32172 .array_type => |array_type| return sema.resolveTypeRequiresComptime(array_type.child.toType()),
32173 .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
32174 .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
32175 .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),
32176 .error_set_type, .inferred_error_set_type => false,
32177
32178 .func_type => true,
32179
32180 .simple_type => |t| switch (t) {
32181 .f16,
32182 .f32,
32183 .f64,
32184 .f80,
32185 .f128,
32186 .usize,
32187 .isize,
32188 .c_char,
32189 .c_short,
32190 .c_ushort,
32191 .c_int,
32192 .c_uint,
32193 .c_long,
32194 .c_ulong,
32195 .c_longlong,
32196 .c_ulonglong,
32197 .c_longdouble,
32198 .anyopaque,
32199 .bool,
32200 .void,
32201 .anyerror,
32202 .noreturn,
32203 .generic_poison,
32204 .atomic_order,
32205 .atomic_rmw_op,
32206 .calling_convention,
32207 .address_space,
32208 .float_mode,
32209 .reduce_op,
32210 .call_modifier,
32211 .prefetch_options,
32212 .export_options,
32213 .extern_options,
32214 => false,
32215
32216 .type,
32217 .comptime_int,
32218 .comptime_float,
32219 .null,
32220 .undefined,
32221 .enum_literal,
32222 .type_info,
32223 => true,
32224 },
32225 .struct_type => |struct_type| {
32226 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
32227 switch (struct_obj.requires_comptime) {
32228 .no, .wip => return false,
32229 .yes => return true,
32230 .unknown => {
32231 var requires_comptime = false;
32232 struct_obj.requires_comptime = .wip;
32233 for (struct_obj.fields.values()) |field| {
32234 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
32235 }
32236 if (requires_comptime) {
32237 struct_obj.requires_comptime = .yes;
32238 } else {
32239 struct_obj.requires_comptime = .no;
32240 }
32241 return requires_comptime;
32242 },
32243 }
32244 },
3141532245
31416 .@"struct" => {
31417 const struct_obj = ty.castTag(.@"struct").?.data;
31418 switch (struct_obj.requires_comptime) {
31419 .no, .wip => return false,
31420 .yes => return true,
31421 .unknown => {
31422 var requires_comptime = false;
31423 struct_obj.requires_comptime = .wip;
31424 for (struct_obj.fields.values()) |field| {
31425 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
32246 .anon_struct_type => |tuple| {
32247 for (tuple.types, tuple.values) |field_ty, field_val| {
32248 const have_comptime_val = field_val != .none;
32249 if (!have_comptime_val and try sema.resolveTypeRequiresComptime(field_ty.toType())) {
32250 return true;
3142632251 }
31427 if (requires_comptime) {
31428 struct_obj.requires_comptime = .yes;
31429 } else {
31430 struct_obj.requires_comptime = .no;
31431 }
31432 return requires_comptime;
31433 },
31434 }
31435 },
32252 }
32253 return false;
32254 },
3143632255
31437 .@"union", .union_safety_tagged, .union_tagged => {
31438 const union_obj = ty.cast(Type.Payload.Union).?.data;
31439 switch (union_obj.requires_comptime) {
31440 .no, .wip => return false,
31441 .yes => return true,
31442 .unknown => {
31443 var requires_comptime = false;
31444 union_obj.requires_comptime = .wip;
31445 for (union_obj.fields.values()) |field| {
31446 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
31447 }
31448 if (requires_comptime) {
31449 union_obj.requires_comptime = .yes;
31450 } else {
31451 union_obj.requires_comptime = .no;
31452 }
31453 return requires_comptime;
31454 },
31455 }
31456 },
32256 .union_type => |union_type| {
32257 const union_obj = mod.unionPtr(union_type.index);
32258 switch (union_obj.requires_comptime) {
32259 .no, .wip => return false,
32260 .yes => return true,
32261 .unknown => {
32262 var requires_comptime = false;
32263 union_obj.requires_comptime = .wip;
32264 for (union_obj.fields.values()) |field| {
32265 if (try sema.resolveTypeRequiresComptime(field.ty)) requires_comptime = true;
32266 }
32267 if (requires_comptime) {
32268 union_obj.requires_comptime = .yes;
32269 } else {
32270 union_obj.requires_comptime = .no;
32271 }
32272 return requires_comptime;
32273 },
32274 }
32275 },
3145732276
31458 .error_union => return sema.resolveTypeRequiresComptime(ty.errorUnionPayload()),
31459 .anyframe_T => {
31460 const child_ty = ty.castTag(.anyframe_T).?.data;
31461 return sema.resolveTypeRequiresComptime(child_ty);
31462 },
31463 .enum_numbered => {
31464 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
31465 return sema.resolveTypeRequiresComptime(tag_ty);
31466 },
31467 .enum_full, .enum_nonexhaustive => {
31468 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
31469 return sema.resolveTypeRequiresComptime(tag_ty);
32277 .opaque_type => false,
32278
32279 .enum_type => |enum_type| try sema.resolveTypeRequiresComptime(enum_type.tag_ty.toType()),
32280
32281 // values, not types
32282 .undef,
32283 .runtime_value,
32284 .simple_value,
32285 .variable,
32286 .extern_func,
32287 .func,
32288 .int,
32289 .err,
32290 .error_union,
32291 .enum_literal,
32292 .enum_tag,
32293 .empty_enum_value,
32294 .float,
32295 .ptr,
32296 .opt,
32297 .aggregate,
32298 .un,
32299 // memoization, not types
32300 .memoized_call,
32301 => unreachable,
3147032302 },
3147132303 };
3147232304}
......@@ -31474,40 +32306,38 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
3147432306/// Returns `error.AnalysisFail` if any of the types (recursively) failed to
3147532307/// be resolved.
3147632308pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
31477 switch (ty.zigTypeTag()) {
32309 const mod = sema.mod;
32310 switch (ty.zigTypeTag(mod)) {
3147832311 .Pointer => {
31479 const child_ty = try sema.resolveTypeFields(ty.childType());
32312 const child_ty = try sema.resolveTypeFields(ty.childType(mod));
3148032313 return sema.resolveTypeFully(child_ty);
3148132314 },
31482 .Struct => switch (ty.tag()) {
31483 .@"struct" => return sema.resolveStructFully(ty),
31484 .tuple, .anon_struct => {
31485 const tuple = ty.tupleFields();
31486
32315 .Struct => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
32316 .struct_type => return sema.resolveStructFully(ty),
32317 .anon_struct_type => |tuple| {
3148732318 for (tuple.types) |field_ty| {
31488 try sema.resolveTypeFully(field_ty);
32319 try sema.resolveTypeFully(field_ty.toType());
3148932320 }
3149032321 },
3149132322 else => {},
3149232323 },
3149332324 .Union => return sema.resolveUnionFully(ty),
31494 .Array => return sema.resolveTypeFully(ty.childType()),
32325 .Array => return sema.resolveTypeFully(ty.childType(mod)),
3149532326 .Optional => {
31496 var buf: Type.Payload.ElemType = undefined;
31497 return sema.resolveTypeFully(ty.optionalChild(&buf));
32327 return sema.resolveTypeFully(ty.optionalChild(mod));
3149832328 },
31499 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload()),
32329 .ErrorUnion => return sema.resolveTypeFully(ty.errorUnionPayload(mod)),
3150032330 .Fn => {
31501 const info = ty.fnInfo();
32331 const info = mod.typeToFunc(ty).?;
3150232332 if (info.is_generic) {
3150332333 // Resolving of generic function types is deferred to when
3150432334 // the function is instantiated.
3150532335 return;
3150632336 }
3150732337 for (info.param_types) |param_ty| {
31508 try sema.resolveTypeFully(param_ty);
32338 try sema.resolveTypeFully(param_ty.toType());
3150932339 }
31510 try sema.resolveTypeFully(info.return_type);
32340 try sema.resolveTypeFully(info.return_type.toType());
3151132341 },
3151232342 else => {},
3151332343 }
......@@ -31516,9 +32346,9 @@ pub fn resolveTypeFully(sema: *Sema, ty: Type) CompileError!void {
3151632346fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
3151732347 try sema.resolveStructLayout(ty);
3151832348
32349 const mod = sema.mod;
3151932350 const resolved_ty = try sema.resolveTypeFields(ty);
31520 const payload = resolved_ty.castTag(.@"struct").?;
31521 const struct_obj = payload.data;
32351 const struct_obj = mod.typeToStruct(resolved_ty).?;
3152232352
3152332353 switch (struct_obj.status) {
3152432354 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
......@@ -31546,8 +32376,9 @@ fn resolveStructFully(sema: *Sema, ty: Type) CompileError!void {
3154632376fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
3154732377 try sema.resolveUnionLayout(ty);
3154832378
32379 const mod = sema.mod;
3154932380 const resolved_ty = try sema.resolveTypeFields(ty);
31550 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
32381 const union_obj = mod.typeToUnion(resolved_ty).?;
3155132382 switch (union_obj.status) {
3155232383 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
3155332384 .fully_resolved_wip, .fully_resolved => return,
......@@ -31572,30 +32403,111 @@ fn resolveUnionFully(sema: *Sema, ty: Type) CompileError!void {
3157232403}
3157332404
3157432405pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type {
31575 switch (ty.tag()) {
31576 .@"struct" => {
31577 const struct_obj = ty.castTag(.@"struct").?.data;
31578 try sema.resolveTypeFieldsStruct(ty, struct_obj);
31579 return ty;
31580 },
31581 .@"union", .union_safety_tagged, .union_tagged => {
31582 const union_obj = ty.cast(Type.Payload.Union).?.data;
31583 try sema.resolveTypeFieldsUnion(ty, union_obj);
31584 return ty;
31585 },
31586 .type_info => return sema.getBuiltinType("Type"),
31587 .extern_options => return sema.getBuiltinType("ExternOptions"),
31588 .export_options => return sema.getBuiltinType("ExportOptions"),
31589 .atomic_order => return sema.getBuiltinType("AtomicOrder"),
31590 .atomic_rmw_op => return sema.getBuiltinType("AtomicRmwOp"),
31591 .calling_convention => return sema.getBuiltinType("CallingConvention"),
31592 .address_space => return sema.getBuiltinType("AddressSpace"),
31593 .float_mode => return sema.getBuiltinType("FloatMode"),
31594 .reduce_op => return sema.getBuiltinType("ReduceOp"),
31595 .modifier => return sema.getBuiltinType("CallModifier"),
31596 .prefetch_options => return sema.getBuiltinType("PrefetchOptions"),
32406 const mod = sema.mod;
32407
32408 switch (ty.toIntern()) {
32409 .var_args_param_type => unreachable,
32410
32411 .none => unreachable,
32412
32413 .u1_type,
32414 .u8_type,
32415 .i8_type,
32416 .u16_type,
32417 .i16_type,
32418 .u29_type,
32419 .u32_type,
32420 .i32_type,
32421 .u64_type,
32422 .i64_type,
32423 .u80_type,
32424 .u128_type,
32425 .i128_type,
32426 .usize_type,
32427 .isize_type,
32428 .c_char_type,
32429 .c_short_type,
32430 .c_ushort_type,
32431 .c_int_type,
32432 .c_uint_type,
32433 .c_long_type,
32434 .c_ulong_type,
32435 .c_longlong_type,
32436 .c_ulonglong_type,
32437 .c_longdouble_type,
32438 .f16_type,
32439 .f32_type,
32440 .f64_type,
32441 .f80_type,
32442 .f128_type,
32443 .anyopaque_type,
32444 .bool_type,
32445 .void_type,
32446 .type_type,
32447 .anyerror_type,
32448 .comptime_int_type,
32449 .comptime_float_type,
32450 .noreturn_type,
32451 .anyframe_type,
32452 .null_type,
32453 .undefined_type,
32454 .enum_literal_type,
32455 .manyptr_u8_type,
32456 .manyptr_const_u8_type,
32457 .manyptr_const_u8_sentinel_0_type,
32458 .single_const_pointer_to_comptime_int_type,
32459 .slice_const_u8_type,
32460 .slice_const_u8_sentinel_0_type,
32461 .anyerror_void_error_union_type,
32462 .generic_poison_type,
32463 .empty_struct_type,
32464 => return ty,
32465
32466 .undef => unreachable,
32467 .zero => unreachable,
32468 .zero_usize => unreachable,
32469 .zero_u8 => unreachable,
32470 .one => unreachable,
32471 .one_usize => unreachable,
32472 .one_u8 => unreachable,
32473 .four_u8 => unreachable,
32474 .negative_one => unreachable,
32475 .calling_convention_c => unreachable,
32476 .calling_convention_inline => unreachable,
32477 .void_value => unreachable,
32478 .unreachable_value => unreachable,
32479 .null_value => unreachable,
32480 .bool_true => unreachable,
32481 .bool_false => unreachable,
32482 .empty_struct => unreachable,
32483 .generic_poison => unreachable,
32484
32485 .type_info_type => return sema.getBuiltinType("Type"),
32486 .extern_options_type => return sema.getBuiltinType("ExternOptions"),
32487 .export_options_type => return sema.getBuiltinType("ExportOptions"),
32488 .atomic_order_type => return sema.getBuiltinType("AtomicOrder"),
32489 .atomic_rmw_op_type => return sema.getBuiltinType("AtomicRmwOp"),
32490 .calling_convention_type => return sema.getBuiltinType("CallingConvention"),
32491 .address_space_type => return sema.getBuiltinType("AddressSpace"),
32492 .float_mode_type => return sema.getBuiltinType("FloatMode"),
32493 .reduce_op_type => return sema.getBuiltinType("ReduceOp"),
32494 .call_modifier_type => return sema.getBuiltinType("CallModifier"),
32495 .prefetch_options_type => return sema.getBuiltinType("PrefetchOptions"),
32496
32497 _ => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
32498 .struct_type => |struct_type| {
32499 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return ty;
32500 try sema.resolveTypeFieldsStruct(ty, struct_obj);
32501 return ty;
32502 },
32503 .union_type => |union_type| {
32504 const union_obj = mod.unionPtr(union_type.index);
32505 try sema.resolveTypeFieldsUnion(ty, union_obj);
32506 return ty;
32507 },
3159732508
31598 else => return ty,
32509 else => return ty,
32510 },
3159932511 }
3160032512}
3160132513
......@@ -31682,35 +32594,39 @@ fn resolveInferredErrorSet(
3168232594 sema: *Sema,
3168332595 block: *Block,
3168432596 src: LazySrcLoc,
31685 ies: *Module.Fn.InferredErrorSet,
32597 ies_index: Module.Fn.InferredErrorSet.Index,
3168632598) CompileError!void {
32599 const mod = sema.mod;
32600 const ies = mod.inferredErrorSetPtr(ies_index);
32601
3168732602 if (ies.is_resolved) return;
3168832603
31689 if (ies.func.state == .in_progress) {
32604 const func = mod.funcPtr(ies.func);
32605 if (func.state == .in_progress) {
3169032606 return sema.fail(block, src, "unable to resolve inferred error set", .{});
3169132607 }
3169232608
3169332609 // In order to ensure that all dependencies are properly added to the set, we
3169432610 // need to ensure the function body is analyzed of the inferred error set.
3169532611 // However, in the case of comptime/inline function calls with inferred error sets,
31696 // each call gets a new InferredErrorSet object, which points to the same
31697 // `*Module.Fn`. Not only is the function not relevant to the inferred error set
32612 // each call gets a new InferredErrorSet object, which contains the same
32613 // `Module.Fn.Index`. Not only is the function not relevant to the inferred error set
3169832614 // in this case, it may be a generic function which would cause an assertion failure
3169932615 // if we called `ensureFuncBodyAnalyzed` on it here.
31700 const ies_func_owner_decl = sema.mod.declPtr(ies.func.owner_decl);
31701 const ies_func_info = ies_func_owner_decl.ty.fnInfo();
32616 const ies_func_owner_decl = mod.declPtr(func.owner_decl);
32617 const ies_func_info = mod.typeToFunc(ies_func_owner_decl.ty).?;
3170232618 // if ies declared by a inline function with generic return type, the return_type should be generic_poison,
3170332619 // because inline function does not create a new declaration, and the ies has been filled with analyzeCall,
3170432620 // so here we can simply skip this case.
31705 if (ies_func_info.return_type.tag() == .generic_poison) {
32621 if (ies_func_info.return_type == .generic_poison_type) {
3170632622 assert(ies_func_info.cc == .Inline);
31707 } else if (ies_func_info.return_type.errorUnionSet().castTag(.error_set_inferred).?.data == ies) {
32623 } else if (mod.typeToInferredErrorSet(ies_func_info.return_type.toType().errorUnionSet(mod)).? == ies) {
3170832624 if (ies_func_info.is_generic) {
3170932625 const msg = msg: {
3171032626 const msg = try sema.errMsg(block, src, "unable to resolve inferred error set of generic function", .{});
3171132627 errdefer msg.destroy(sema.gpa);
3171232628
31713 try sema.mod.errNoteNonLazy(ies_func_owner_decl.srcLoc(), msg, "generic function declared here", .{});
32629 try sema.mod.errNoteNonLazy(ies_func_owner_decl.srcLoc(mod), msg, "generic function declared here", .{});
3171432630 break :msg msg;
3171532631 };
3171632632 return sema.failWithOwnedErrorMsg(msg);
......@@ -31722,10 +32638,11 @@ fn resolveInferredErrorSet(
3172232638
3172332639 ies.is_resolved = true;
3172432640
31725 for (ies.inferred_error_sets.keys()) |other_ies| {
31726 if (ies == other_ies) continue;
31727 try sema.resolveInferredErrorSet(block, src, other_ies);
32641 for (ies.inferred_error_sets.keys()) |other_ies_index| {
32642 if (ies_index == other_ies_index) continue;
32643 try sema.resolveInferredErrorSet(block, src, other_ies_index);
3172832644
32645 const other_ies = mod.inferredErrorSetPtr(other_ies_index);
3172932646 for (other_ies.errors.keys()) |key| {
3173032647 try ies.errors.put(sema.gpa, key, {});
3173132648 }
......@@ -31740,15 +32657,17 @@ fn resolveInferredErrorSetTy(
3174032657 src: LazySrcLoc,
3174132658 ty: Type,
3174232659) CompileError!void {
31743 if (ty.castTag(.error_set_inferred)) |inferred| {
31744 try sema.resolveInferredErrorSet(block, src, inferred.data);
32660 const mod = sema.mod;
32661 if (mod.typeToInferredErrorSetIndex(ty).unwrap()) |ies_index| {
32662 try sema.resolveInferredErrorSet(block, src, ies_index);
3174532663 }
3174632664}
3174732665
3174832666fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void {
3174932667 const gpa = mod.gpa;
32668 const ip = &mod.intern_pool;
3175032669 const decl_index = struct_obj.owner_decl;
31751 const zir = struct_obj.namespace.file_scope.zir;
32670 const zir = mod.namespacePtr(struct_obj.namespace).file_scope.zir;
3175232671 const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended;
3175332672 assert(extended.opcode == .struct_decl);
3175432673 const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small);
......@@ -31794,35 +32713,37 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3179432713 }
3179532714
3179632715 const decl = mod.declPtr(decl_index);
31797 var decl_arena: std.heap.ArenaAllocator = undefined;
31798 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
31799 defer decl.value_arena.?.release(&decl_arena);
3180032716
3180132717 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3180232718 defer analysis_arena.deinit();
3180332719
32720 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
32721 defer comptime_mutable_decls.deinit();
32722
3180432723 var sema: Sema = .{
3180532724 .mod = mod,
3180632725 .gpa = gpa,
3180732726 .arena = analysis_arena.allocator(),
31808 .perm_arena = decl_arena_allocator,
3180932727 .code = zir,
3181032728 .owner_decl = decl,
3181132729 .owner_decl_index = decl_index,
3181232730 .func = null,
32731 .func_index = .none,
3181332732 .fn_ret_ty = Type.void,
3181432733 .owner_func = null,
32734 .owner_func_index = .none,
32735 .comptime_mutable_decls = &comptime_mutable_decls,
3181532736 };
3181632737 defer sema.deinit();
3181732738
31818 var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
32739 var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope);
3181932740 defer wip_captures.deinit();
3182032741
3182132742 var block_scope: Block = .{
3182232743 .parent = null,
3182332744 .sema = &sema,
3182432745 .src_decl = decl_index,
31825 .namespace = &struct_obj.namespace,
32746 .namespace = struct_obj.namespace,
3182632747 .wip_capture_scope = wip_captures.scope,
3182732748 .instructions = .{},
3182832749 .inlining = null,
......@@ -31834,13 +32755,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3183432755 }
3183532756
3183632757 struct_obj.fields = .{};
31837 try struct_obj.fields.ensureTotalCapacity(decl_arena_allocator, fields_len);
32758 try struct_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);
3183832759
3183932760 const Field = struct {
3184032761 type_body_len: u32 = 0,
3184132762 align_body_len: u32 = 0,
3184232763 init_body_len: u32 = 0,
31843 type_ref: Air.Inst.Ref = .none,
32764 type_ref: Zir.Inst.Ref = .none,
3184432765 };
3184532766 const fields = try sema.arena.alloc(Field, fields_len);
3184632767 var any_inits = false;
......@@ -31885,30 +32806,30 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3188532806 extra_index += 1;
3188632807
3188732808 // This string needs to outlive the ZIR code.
31888 const field_name = if (field_name_zir) |some|
31889 try decl_arena_allocator.dupe(u8, some)
32809 const field_name = try ip.getOrPutString(gpa, if (field_name_zir) |s|
32810 s
3189032811 else
31891 try std.fmt.allocPrint(decl_arena_allocator, "{d}", .{field_i});
32812 try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}));
3189232813
3189332814 const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name);
3189432815 if (gop.found_existing) {
3189532816 const msg = msg: {
31896 const field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
31897 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{s}'", .{field_name});
32817 const field_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{ .index = field_i }).lazy;
32818 const msg = try sema.errMsg(&block_scope, field_src, "duplicate struct field: '{}'", .{field_name.fmt(ip)});
3189832819 errdefer msg.destroy(gpa);
3189932820
3190032821 const prev_field_index = struct_obj.fields.getIndex(field_name).?;
31901 const prev_field_src = struct_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index });
31902 try sema.mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
32822 const prev_field_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{ .index = prev_field_index });
32823 try mod.errNoteNonLazy(prev_field_src, msg, "other field here", .{});
3190332824 try sema.errNote(&block_scope, src, msg, "struct declared here", .{});
3190432825 break :msg msg;
3190532826 };
3190632827 return sema.failWithOwnedErrorMsg(msg);
3190732828 }
3190832829 gop.value_ptr.* = .{
31909 .ty = Type.initTag(.noreturn),
32830 .ty = Type.noreturn,
3191032831 .abi_align = 0,
31911 .default_val = Value.initTag(.unreachable_value),
32832 .default_val = .none,
3191232833 .is_comptime = is_comptime,
3191332834 .offset = undefined,
3191432835 };
......@@ -31934,7 +32855,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3193432855 if (zir_field.type_ref != .none) {
3193532856 break :ty sema.resolveType(&block_scope, .unneeded, zir_field.type_ref) catch |err| switch (err) {
3193632857 error.NeededSourceLocation => {
31937 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
32858 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3193832859 .index = field_i,
3193932860 .range = .type,
3194032861 }).lazy;
......@@ -31950,7 +32871,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3195032871 const ty_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
3195132872 break :ty sema.analyzeAsType(&block_scope, .unneeded, ty_ref) catch |err| switch (err) {
3195232873 error.NeededSourceLocation => {
31953 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
32874 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3195432875 .index = field_i,
3195532876 .range = .type,
3195632877 }).lazy;
......@@ -31960,16 +32881,16 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3196032881 else => |e| return e,
3196132882 };
3196232883 };
31963 if (field_ty.tag() == .generic_poison) {
32884 if (field_ty.isGenericPoison()) {
3196432885 return error.GenericPoison;
3196532886 }
3196632887
3196732888 const field = &struct_obj.fields.values()[field_i];
31968 field.ty = try field_ty.copy(decl_arena_allocator);
32889 field.ty = field_ty;
3196932890
31970 if (field_ty.zigTypeTag() == .Opaque) {
32891 if (field_ty.zigTypeTag(mod) == .Opaque) {
3197132892 const msg = msg: {
31972 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
32893 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3197332894 .index = field_i,
3197432895 .range = .type,
3197532896 }).lazy;
......@@ -31981,9 +32902,9 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3198132902 };
3198232903 return sema.failWithOwnedErrorMsg(msg);
3198332904 }
31984 if (field_ty.zigTypeTag() == .NoReturn) {
32905 if (field_ty.zigTypeTag(mod) == .NoReturn) {
3198532906 const msg = msg: {
31986 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
32907 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3198732908 .index = field_i,
3198832909 .range = .type,
3198932910 }).lazy;
......@@ -31997,11 +32918,11 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3199732918 }
3199832919 if (struct_obj.layout == .Extern and !try sema.validateExternType(field.ty, .struct_field)) {
3199932920 const msg = msg: {
32000 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
32921 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3200132922 .index = field_i,
3200232923 .range = .type,
3200332924 });
32004 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
32925 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern structs cannot contain fields of type '{}'", .{field.ty.fmt(mod)});
3200532926 errdefer msg.destroy(sema.gpa);
3200632927
3200732928 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field.ty, .struct_field);
......@@ -32010,13 +32931,13 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3201032931 break :msg msg;
3201132932 };
3201232933 return sema.failWithOwnedErrorMsg(msg);
32013 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty))) {
32934 } else if (struct_obj.layout == .Packed and !(validatePackedType(field.ty, mod))) {
3201432935 const msg = msg: {
32015 const ty_src = struct_obj.fieldSrcLoc(sema.mod, .{
32936 const ty_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3201632937 .index = field_i,
3201732938 .range = .type,
3201832939 });
32019 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(sema.mod)});
32940 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed structs cannot contain fields of type '{}'", .{field.ty.fmt(mod)});
3202032941 errdefer msg.destroy(sema.gpa);
3202132942
3202232943 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field.ty);
......@@ -32033,7 +32954,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3203332954 const align_ref = try sema.resolveBody(&block_scope, body, struct_obj.zir_index);
3203432955 field.abi_align = sema.analyzeAsAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
3203532956 error.NeededSourceLocation => {
32036 const align_src = struct_obj.fieldSrcLoc(sema.mod, .{
32957 const align_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3203732958 .index = field_i,
3203832959 .range = .alignment,
3203932960 }).lazy;
......@@ -32061,7 +32982,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3206132982 const field = &struct_obj.fields.values()[field_i];
3206232983 const coerced = sema.coerce(&block_scope, field.ty, init, .unneeded) catch |err| switch (err) {
3206332984 error.NeededSourceLocation => {
32064 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
32985 const init_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3206532986 .index = field_i,
3206632987 .range = .value,
3206732988 }).lazy;
......@@ -32071,17 +32992,21 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3207132992 else => |e| return e,
3207232993 };
3207332994 const default_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
32074 const init_src = struct_obj.fieldSrcLoc(sema.mod, .{
32995 const init_src = mod.fieldSrcLoc(struct_obj.owner_decl, .{
3207532996 .index = field_i,
3207632997 .range = .value,
3207732998 }).lazy;
3207832999 return sema.failWithNeededComptime(&block_scope, init_src, "struct field default value must be comptime-known");
3207933000 };
32080 field.default_val = try default_val.copy(decl_arena_allocator);
33001 field.default_val = try default_val.intern(field.ty, mod);
3208133002 }
3208233003 }
3208333004 }
3208433005 try wip_captures.finalize();
33006 for (comptime_mutable_decls.items) |ct_decl_index| {
33007 const ct_decl = mod.declPtr(ct_decl_index);
33008 try ct_decl.intern(mod);
33009 }
3208533010
3208633011 struct_obj.have_field_inits = true;
3208733012}
......@@ -32091,8 +33016,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3209133016 defer tracy.end();
3209233017
3209333018 const gpa = mod.gpa;
33019 const ip = &mod.intern_pool;
3209433020 const decl_index = union_obj.owner_decl;
32095 const zir = union_obj.namespace.file_scope.zir;
33021 const zir = mod.namespacePtr(union_obj.namespace).file_scope.zir;
3209633022 const extended = zir.instructions.items(.data)[union_obj.zir_index].extended;
3209733023 assert(extended.opcode == .union_decl);
3209833024 const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small);
......@@ -32134,35 +33060,37 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3213433060 extra_index += body.len;
3213533061
3213633062 const decl = mod.declPtr(decl_index);
32137 var decl_arena: std.heap.ArenaAllocator = undefined;
32138 const decl_arena_allocator = decl.value_arena.?.acquire(gpa, &decl_arena);
32139 defer decl.value_arena.?.release(&decl_arena);
3214033063
3214133064 var analysis_arena = std.heap.ArenaAllocator.init(gpa);
3214233065 defer analysis_arena.deinit();
3214333066
33067 var comptime_mutable_decls = std.ArrayList(Decl.Index).init(gpa);
33068 defer comptime_mutable_decls.deinit();
33069
3214433070 var sema: Sema = .{
3214533071 .mod = mod,
3214633072 .gpa = gpa,
3214733073 .arena = analysis_arena.allocator(),
32148 .perm_arena = decl_arena_allocator,
3214933074 .code = zir,
3215033075 .owner_decl = decl,
3215133076 .owner_decl_index = decl_index,
3215233077 .func = null,
33078 .func_index = .none,
3215333079 .fn_ret_ty = Type.void,
3215433080 .owner_func = null,
33081 .owner_func_index = .none,
33082 .comptime_mutable_decls = &comptime_mutable_decls,
3215533083 };
3215633084 defer sema.deinit();
3215733085
32158 var wip_captures = try WipCaptureScope.init(gpa, decl_arena_allocator, decl.src_scope);
33086 var wip_captures = try WipCaptureScope.init(gpa, decl.src_scope);
3215933087 defer wip_captures.deinit();
3216033088
3216133089 var block_scope: Block = .{
3216233090 .parent = null,
3216333091 .sema = &sema,
3216433092 .src_decl = decl_index,
32165 .namespace = &union_obj.namespace,
33093 .namespace = union_obj.namespace,
3216633094 .wip_capture_scope = wip_captures.scope,
3216733095 .instructions = .{},
3216833096 .inlining = null,
......@@ -32178,66 +33106,61 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3217833106 }
3217933107
3218033108 try wip_captures.finalize();
33109 for (comptime_mutable_decls.items) |ct_decl_index| {
33110 const ct_decl = mod.declPtr(ct_decl_index);
33111 try ct_decl.intern(mod);
33112 }
3218133113
32182 try union_obj.fields.ensureTotalCapacity(decl_arena_allocator, fields_len);
33114 try union_obj.fields.ensureTotalCapacity(mod.tmp_hack_arena.allocator(), fields_len);
3218333115
3218433116 var int_tag_ty: Type = undefined;
32185 var enum_field_names: ?*Module.EnumNumbered.NameMap = null;
32186 var enum_value_map: ?*Module.EnumNumbered.ValueMap = null;
32187 var tag_ty_field_names: ?Module.EnumFull.NameMap = null;
33117 var enum_field_names: []InternPool.NullTerminatedString = &.{};
33118 var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{};
33119 var explicit_tags_seen: []bool = &.{};
3218833120 if (tag_type_ref != .none) {
3218933121 const tag_ty_src: LazySrcLoc = .{ .node_offset_container_tag = src.node_offset.x };
3219033122 const provided_ty = try sema.resolveType(&block_scope, tag_ty_src, tag_type_ref);
3219133123 if (small.auto_enum_tag) {
3219233124 // The provided type is an integer type and we must construct the enum tag type here.
3219333125 int_tag_ty = provided_ty;
32194 if (int_tag_ty.zigTypeTag() != .Int and int_tag_ty.zigTypeTag() != .ComptimeInt) {
32195 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(sema.mod)});
33126 if (int_tag_ty.zigTypeTag(mod) != .Int and int_tag_ty.zigTypeTag(mod) != .ComptimeInt) {
33127 return sema.fail(&block_scope, tag_ty_src, "expected integer tag type, found '{}'", .{int_tag_ty.fmt(mod)});
3219633128 }
3219733129
3219833130 if (fields_len > 0) {
32199 var field_count_val: Value.Payload.U64 = .{
32200 .base = .{ .tag = .int_u64 },
32201 .data = fields_len - 1,
32202 };
32203 if (!(try sema.intFitsInType(Value.initPayload(&field_count_val.base), int_tag_ty, null))) {
33131 const field_count_val = try mod.intValue(Type.comptime_int, fields_len - 1);
33132 if (!(try sema.intFitsInType(field_count_val, int_tag_ty, null))) {
3220433133 const msg = msg: {
3220533134 const msg = try sema.errMsg(&block_scope, tag_ty_src, "specified integer tag type cannot represent every field", .{});
3220633135 errdefer msg.destroy(sema.gpa);
3220733136 try sema.errNote(&block_scope, tag_ty_src, msg, "type '{}' cannot fit values in range 0...{d}", .{
32208 int_tag_ty.fmt(sema.mod),
33137 int_tag_ty.fmt(mod),
3220933138 fields_len - 1,
3221033139 });
3221133140 break :msg msg;
3221233141 };
3221333142 return sema.failWithOwnedErrorMsg(msg);
3221433143 }
33144 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
33145 try enum_field_vals.ensureTotalCapacity(sema.arena, fields_len);
3221533146 }
32216 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty, union_obj);
32217 const enum_obj = union_obj.tag_ty.castTag(.enum_numbered).?.data;
32218 enum_field_names = &enum_obj.fields;
32219 enum_value_map = &enum_obj.values;
3222033147 } else {
3222133148 // The provided type is the enum tag type.
32222 union_obj.tag_ty = try provided_ty.copy(decl_arena_allocator);
32223 if (union_obj.tag_ty.zigTypeTag() != .Enum) {
32224 return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(sema.mod)});
32225 }
33149 union_obj.tag_ty = provided_ty;
33150 const enum_type = switch (ip.indexToKey(union_obj.tag_ty.toIntern())) {
33151 .enum_type => |x| x,
33152 else => return sema.fail(&block_scope, tag_ty_src, "expected enum tag type, found '{}'", .{union_obj.tag_ty.fmt(mod)}),
33153 };
3222633154 // The fields of the union must match the enum exactly.
32227 // Store a copy of the enum field names so we can check for
32228 // missing or extraneous fields later.
32229 tag_ty_field_names = try union_obj.tag_ty.enumFields().clone(sema.arena);
33155 // A flag per field is used to check for missing and extraneous fields.
33156 explicit_tags_seen = try sema.arena.alloc(bool, enum_type.names.len);
33157 @memset(explicit_tags_seen, false);
3223033158 }
3223133159 } else {
3223233160 // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis
3223333161 // purposes, we still auto-generate an enum tag type the same way. That the union is
3223433162 // untagged is represented by the Type tag (union vs union_tagged).
32235 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, fields_len, union_obj);
32236 enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields;
32237 }
32238
32239 if (fields_len == 0) {
32240 return;
33163 enum_field_names = try sema.arena.alloc(InternPool.NullTerminatedString, fields_len);
3224133164 }
3224233165
3224333166 const bits_per_field = 4;
......@@ -32281,17 +33204,17 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3228133204 break :blk align_ref;
3228233205 } else .none;
3228333206
32284 const tag_ref: Zir.Inst.Ref = if (has_tag) blk: {
33207 const tag_ref: Air.Inst.Ref = if (has_tag) blk: {
3228533208 const tag_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
3228633209 extra_index += 1;
3228733210 break :blk try sema.resolveInst(tag_ref);
3228833211 } else .none;
3228933212
32290 if (enum_value_map) |map| {
32291 const copied_val = if (tag_ref != .none) blk: {
33213 if (enum_field_vals.capacity() > 0) {
33214 const enum_tag_val = if (tag_ref != .none) blk: {
3229233215 const val = sema.semaUnionFieldVal(&block_scope, .unneeded, int_tag_ty, tag_ref) catch |err| switch (err) {
3229333216 error.NeededSourceLocation => {
32294 const val_src = union_obj.fieldSrcLoc(sema.mod, .{
33217 const val_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3229533218 .index = field_i,
3229633219 .range = .value,
3229733220 }).lazy;
......@@ -32302,27 +33225,22 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3230233225 };
3230333226 last_tag_val = val;
3230433227
32305 // This puts the memory into the union arena, not the enum arena, but
32306 // it is OK since they share the same lifetime.
32307 break :blk try val.copy(decl_arena_allocator);
33228 break :blk val;
3230833229 } else blk: {
3230933230 const val = if (last_tag_val) |val|
32310 try sema.intAdd(val, Value.one, int_tag_ty)
33231 try sema.intAdd(val, Value.one_comptime_int, int_tag_ty, undefined)
3231133232 else
32312 Value.zero;
33233 try mod.intValue(int_tag_ty, 0);
3231333234 last_tag_val = val;
3231433235
32315 break :blk try val.copy(decl_arena_allocator);
33236 break :blk val;
3231633237 };
32317 const gop = map.getOrPutAssumeCapacityContext(copied_val, .{
32318 .ty = int_tag_ty,
32319 .mod = mod,
32320 });
33238 const gop = enum_field_vals.getOrPutAssumeCapacity(enum_tag_val.toIntern());
3232133239 if (gop.found_existing) {
32322 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
32323 const other_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = gop.index }).lazy;
33240 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
33241 const other_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = gop.index }).lazy;
3232433242 const msg = msg: {
32325 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{copied_val.fmtValue(int_tag_ty, sema.mod)});
33243 const msg = try sema.errMsg(&block_scope, field_src, "enum tag value {} already taken", .{enum_tag_val.fmtValue(int_tag_ty, mod)});
3232633244 errdefer msg.destroy(gpa);
3232733245 try sema.errNote(&block_scope, other_field_src, msg, "other occurrence here", .{});
3232833246 break :msg msg;
......@@ -32332,19 +33250,19 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3233233250 }
3233333251
3233433252 // This string needs to outlive the ZIR code.
32335 const field_name = try decl_arena_allocator.dupe(u8, field_name_zir);
32336 if (enum_field_names) |set| {
32337 set.putAssumeCapacity(field_name, {});
33253 const field_name = try ip.getOrPutString(gpa, field_name_zir);
33254 if (enum_field_names.len != 0) {
33255 enum_field_names[field_i] = field_name;
3233833256 }
3233933257
3234033258 const field_ty: Type = if (!has_type)
3234133259 Type.void
3234233260 else if (field_type_ref == .none)
32343 Type.initTag(.noreturn)
33261 Type.noreturn
3234433262 else
3234533263 sema.resolveType(&block_scope, .unneeded, field_type_ref) catch |err| switch (err) {
3234633264 error.NeededSourceLocation => {
32347 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
33265 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3234833266 .index = field_i,
3234933267 .range = .type,
3235033268 }).lazy;
......@@ -32354,46 +33272,54 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3235433272 else => |e| return e,
3235533273 };
3235633274
32357 if (field_ty.tag() == .generic_poison) {
33275 if (field_ty.isGenericPoison()) {
3235833276 return error.GenericPoison;
3235933277 }
3236033278
3236133279 const gop = union_obj.fields.getOrPutAssumeCapacity(field_name);
3236233280 if (gop.found_existing) {
3236333281 const msg = msg: {
32364 const field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = field_i }).lazy;
32365 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{s}'", .{field_name});
33282 const field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = field_i }).lazy;
33283 const msg = try sema.errMsg(&block_scope, field_src, "duplicate union field: '{}'", .{
33284 field_name.fmt(ip),
33285 });
3236633286 errdefer msg.destroy(gpa);
3236733287
3236833288 const prev_field_index = union_obj.fields.getIndex(field_name).?;
32369 const prev_field_src = union_obj.fieldSrcLoc(sema.mod, .{ .index = prev_field_index }).lazy;
32370 try sema.mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl), msg, "other field here", .{});
33289 const prev_field_src = mod.fieldSrcLoc(union_obj.owner_decl, .{ .index = prev_field_index }).lazy;
33290 try mod.errNoteNonLazy(prev_field_src.toSrcLoc(decl, mod), msg, "other field here", .{});
3237133291 try sema.errNote(&block_scope, src, msg, "union declared here", .{});
3237233292 break :msg msg;
3237333293 };
3237433294 return sema.failWithOwnedErrorMsg(msg);
3237533295 }
3237633296
32377 if (tag_ty_field_names) |*names| {
32378 const enum_has_field = names.orderedRemove(field_name);
32379 if (!enum_has_field) {
33297 if (explicit_tags_seen.len > 0) {
33298 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
33299 const enum_index = tag_info.nameIndex(ip, field_name) orelse {
3238033300 const msg = msg: {
32381 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
33301 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3238233302 .index = field_i,
3238333303 .range = .type,
3238433304 }).lazy;
32385 const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{s}' in enum '{}'", .{ field_name, union_obj.tag_ty.fmt(sema.mod) });
33305 const msg = try sema.errMsg(&block_scope, ty_src, "no field named '{}' in enum '{}'", .{
33306 field_name.fmt(ip), union_obj.tag_ty.fmt(mod),
33307 });
3238633308 errdefer msg.destroy(sema.gpa);
3238733309 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
3238833310 break :msg msg;
3238933311 };
3239033312 return sema.failWithOwnedErrorMsg(msg);
32391 }
33313 };
33314 // No check for duplicate because the check already happened in order
33315 // to create the enum type in the first place.
33316 assert(!explicit_tags_seen[enum_index]);
33317 explicit_tags_seen[enum_index] = true;
3239233318 }
3239333319
32394 if (field_ty.zigTypeTag() == .Opaque) {
33320 if (field_ty.zigTypeTag(mod) == .Opaque) {
3239533321 const msg = msg: {
32396 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
33322 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3239733323 .index = field_i,
3239833324 .range = .type,
3239933325 }).lazy;
......@@ -32407,11 +33333,11 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3240733333 }
3240833334 if (union_obj.layout == .Extern and !try sema.validateExternType(field_ty, .union_field)) {
3240933335 const msg = msg: {
32410 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
33336 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3241133337 .index = field_i,
3241233338 .range = .type,
3241333339 });
32414 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
33340 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "extern unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
3241533341 errdefer msg.destroy(sema.gpa);
3241633342
3241733343 try sema.explainWhyTypeIsNotExtern(msg, ty_src, field_ty, .union_field);
......@@ -32420,13 +33346,13 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3242033346 break :msg msg;
3242133347 };
3242233348 return sema.failWithOwnedErrorMsg(msg);
32423 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty))) {
33349 } else if (union_obj.layout == .Packed and !(validatePackedType(field_ty, mod))) {
3242433350 const msg = msg: {
32425 const ty_src = union_obj.fieldSrcLoc(sema.mod, .{
33351 const ty_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3242633352 .index = field_i,
3242733353 .range = .type,
3242833354 });
32429 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(sema.mod)});
33355 const msg = try sema.errMsg(&block_scope, ty_src.lazy, "packed unions cannot contain fields of type '{}'", .{field_ty.fmt(mod)});
3243033356 errdefer msg.destroy(sema.gpa);
3243133357
3243233358 try sema.explainWhyTypeIsNotPacked(msg, ty_src, field_ty);
......@@ -32438,14 +33364,14 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3243833364 }
3243933365
3244033366 gop.value_ptr.* = .{
32441 .ty = try field_ty.copy(decl_arena_allocator),
33367 .ty = field_ty,
3244233368 .abi_align = 0,
3244333369 };
3244433370
3244533371 if (align_ref != .none) {
3244633372 gop.value_ptr.abi_align = sema.resolveAlign(&block_scope, .unneeded, align_ref) catch |err| switch (err) {
3244733373 error.NeededSourceLocation => {
32448 const align_src = union_obj.fieldSrcLoc(sema.mod, .{
33374 const align_src = mod.fieldSrcLoc(union_obj.owner_decl, .{
3244933375 .index = field_i,
3245033376 .range = .alignment,
3245133377 }).lazy;
......@@ -32459,22 +33385,29 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3245933385 }
3246033386 }
3246133387
32462 if (tag_ty_field_names) |names| {
32463 if (names.count() > 0) {
33388 if (explicit_tags_seen.len > 0) {
33389 const tag_info = ip.indexToKey(union_obj.tag_ty.toIntern()).enum_type;
33390 if (tag_info.names.len > fields_len) {
3246433391 const msg = msg: {
3246533392 const msg = try sema.errMsg(&block_scope, src, "enum field(s) missing in union", .{});
3246633393 errdefer msg.destroy(sema.gpa);
3246733394
3246833395 const enum_ty = union_obj.tag_ty;
32469 for (names.keys()) |field_name| {
32470 const field_index = enum_ty.enumFieldIndex(field_name).?;
32471 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{s}' missing, declared here", .{field_name});
33396 for (tag_info.names, 0..) |field_name, field_index| {
33397 if (explicit_tags_seen[field_index]) continue;
33398 try sema.addFieldErrNote(enum_ty, field_index, msg, "field '{}' missing, declared here", .{
33399 field_name.fmt(ip),
33400 });
3247233401 }
3247333402 try sema.addDeclaredHereNote(msg, union_obj.tag_ty);
3247433403 break :msg msg;
3247533404 };
3247633405 return sema.failWithOwnedErrorMsg(msg);
3247733406 }
33407 } else if (enum_field_vals.count() > 0) {
33408 union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, enum_field_names, enum_field_vals.keys(), union_obj);
33409 } else {
33410 union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, enum_field_names, union_obj);
3247833411 }
3247933412}
3248033413
......@@ -32486,116 +33419,103 @@ fn semaUnionFieldVal(sema: *Sema, block: *Block, src: LazySrcLoc, int_tag_ty: Ty
3248633419fn generateUnionTagTypeNumbered(
3248733420 sema: *Sema,
3248833421 block: *Block,
32489 fields_len: u32,
32490 int_ty: Type,
33422 enum_field_names: []const InternPool.NullTerminatedString,
33423 enum_field_vals: []const InternPool.Index,
3249133424 union_obj: *Module.Union,
3249233425) !Type {
3249333426 const mod = sema.mod;
32494
32495 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
32496 errdefer new_decl_arena.deinit();
32497 const new_decl_arena_allocator = new_decl_arena.allocator();
32498
32499 const enum_obj = try new_decl_arena_allocator.create(Module.EnumNumbered);
32500 const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumNumbered);
32501 enum_ty_payload.* = .{
32502 .base = .{ .tag = .enum_numbered },
32503 .data = enum_obj,
32504 };
32505 const enum_ty = Type.initPayload(&enum_ty_payload.base);
32506 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
33427 const gpa = sema.gpa;
3250733428
3250833429 const src_decl = mod.declPtr(block.src_decl);
3250933430 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
3251033431 errdefer mod.destroyDecl(new_decl_index);
32511 const name = name: {
32512 const fqn = try union_obj.getFullyQualifiedName(mod);
32513 defer sema.gpa.free(fqn);
32514 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
32515 };
33432 const fqn = try union_obj.getFullyQualifiedName(mod);
33433 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
3251633434 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
32517 .ty = Type.type,
32518 .val = enum_val,
33435 .ty = Type.noreturn,
33436 .val = Value.@"unreachable",
3251933437 }, name);
32520 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
33438 errdefer mod.abortAnonDecl(new_decl_index);
3252133439
3252233440 const new_decl = mod.declPtr(new_decl_index);
33441 new_decl.name_fully_qualified = true;
3252333442 new_decl.owns_tv = true;
3252433443 new_decl.name_fully_qualified = true;
32525 errdefer mod.abortAnonDecl(new_decl_index);
3252633444
32527 const copied_int_ty = try int_ty.copy(new_decl_arena_allocator);
32528 enum_obj.* = .{
32529 .owner_decl = new_decl_index,
32530 .tag_ty = copied_int_ty,
32531 .fields = .{},
32532 .values = .{},
32533 };
32534 // Here we pre-allocate the maps using the decl arena.
32535 try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
32536 try enum_obj.values.ensureTotalCapacityContext(new_decl_arena_allocator, fields_len, .{
32537 .ty = copied_int_ty,
32538 .mod = mod,
32539 });
32540 try new_decl.finalizeNewArena(&new_decl_arena);
32541 return enum_ty;
32542}
33445 const enum_ty = try mod.intern(.{ .enum_type = .{
33446 .decl = new_decl_index,
33447 .namespace = .none,
33448 .tag_ty = if (enum_field_vals.len == 0)
33449 (try mod.intType(.unsigned, 0)).toIntern()
33450 else
33451 mod.intern_pool.typeOf(enum_field_vals[0]),
33452 .names = enum_field_names,
33453 .values = enum_field_vals,
33454 .tag_mode = .explicit,
33455 } });
3254333456
32544fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: usize, maybe_union_obj: ?*Module.Union) !Type {
32545 const mod = sema.mod;
33457 new_decl.ty = Type.type;
33458 new_decl.val = enum_ty.toValue();
3254633459
32547 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
32548 errdefer new_decl_arena.deinit();
32549 const new_decl_arena_allocator = new_decl_arena.allocator();
33460 try mod.finalizeAnonDecl(new_decl_index);
33461 return enum_ty.toType();
33462}
3255033463
32551 const enum_obj = try new_decl_arena_allocator.create(Module.EnumSimple);
32552 const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumSimple);
32553 enum_ty_payload.* = .{
32554 .base = .{ .tag = .enum_simple },
32555 .data = enum_obj,
32556 };
32557 const enum_ty = Type.initPayload(&enum_ty_payload.base);
32558 const enum_val = try Value.Tag.ty.create(new_decl_arena_allocator, enum_ty);
33464fn generateUnionTagTypeSimple(
33465 sema: *Sema,
33466 block: *Block,
33467 enum_field_names: []const InternPool.NullTerminatedString,
33468 maybe_union_obj: ?*Module.Union,
33469) !Type {
33470 const mod = sema.mod;
33471 const gpa = sema.gpa;
3255933472
3256033473 const new_decl_index = new_decl_index: {
3256133474 const union_obj = maybe_union_obj orelse {
3256233475 break :new_decl_index try mod.createAnonymousDecl(block, .{
32563 .ty = Type.type,
32564 .val = enum_val,
33476 .ty = Type.noreturn,
33477 .val = Value.@"unreachable",
3256533478 });
3256633479 };
3256733480 const src_decl = mod.declPtr(block.src_decl);
3256833481 const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node, block.wip_capture_scope);
3256933482 errdefer mod.destroyDecl(new_decl_index);
32570 const name = name: {
32571 const fqn = try union_obj.getFullyQualifiedName(mod);
32572 defer sema.gpa.free(fqn);
32573 break :name try std.fmt.allocPrintZ(mod.gpa, "@typeInfo({s}).Union.tag_type.?", .{fqn});
32574 };
33483 const fqn = try union_obj.getFullyQualifiedName(mod);
33484 const name = try mod.intern_pool.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(&mod.intern_pool)});
3257533485 try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, block.namespace, .{
32576 .ty = Type.type,
32577 .val = enum_val,
33486 .ty = Type.noreturn,
33487 .val = Value.@"unreachable",
3257833488 }, name);
32579 sema.mod.declPtr(new_decl_index).name_fully_qualified = true;
33489 mod.declPtr(new_decl_index).name_fully_qualified = true;
3258033490 break :new_decl_index new_decl_index;
3258133491 };
33492 errdefer mod.abortAnonDecl(new_decl_index);
33493
33494 const enum_ty = try mod.intern(.{ .enum_type = .{
33495 .decl = new_decl_index,
33496 .namespace = .none,
33497 .tag_ty = if (enum_field_names.len == 0)
33498 (try mod.intType(.unsigned, 0)).toIntern()
33499 else
33500 (try mod.smallestUnsignedInt(enum_field_names.len - 1)).toIntern(),
33501 .names = enum_field_names,
33502 .values = &.{},
33503 .tag_mode = .auto,
33504 } });
3258233505
3258333506 const new_decl = mod.declPtr(new_decl_index);
3258433507 new_decl.owns_tv = true;
32585 errdefer mod.abortAnonDecl(new_decl_index);
33508 new_decl.ty = Type.type;
33509 new_decl.val = enum_ty.toValue();
3258633510
32587 enum_obj.* = .{
32588 .owner_decl = new_decl_index,
32589 .fields = .{},
32590 };
32591 // Here we pre-allocate the maps using the decl arena.
32592 try enum_obj.fields.ensureTotalCapacity(new_decl_arena_allocator, fields_len);
32593 try new_decl.finalizeNewArena(&new_decl_arena);
32594 return enum_ty;
33511 try mod.finalizeAnonDecl(new_decl_index);
33512 return enum_ty.toType();
3259533513}
3259633514
3259733515fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
32598 var wip_captures = try WipCaptureScope.init(sema.gpa, sema.perm_arena, sema.owner_decl.src_scope);
33516 const gpa = sema.gpa;
33517
33518 var wip_captures = try WipCaptureScope.init(gpa, sema.owner_decl.src_scope);
3259933519 defer wip_captures.deinit();
3260033520
3260133521 var block: Block = .{
......@@ -32609,19 +33529,20 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
3260933529 .is_comptime = true,
3261033530 };
3261133531 defer {
32612 block.instructions.deinit(sema.gpa);
32613 block.params.deinit(sema.gpa);
33532 block.instructions.deinit(gpa);
33533 block.params.deinit(gpa);
3261433534 }
3261533535 const src = LazySrcLoc.nodeOffset(0);
3261633536
3261733537 const mod = sema.mod;
33538 const ip = &mod.intern_pool;
3261833539 const std_pkg = mod.main_pkg.table.get("std").?;
3261933540 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;
3262033541 const opt_builtin_inst = (try sema.namespaceLookupRef(
3262133542 &block,
3262233543 src,
3262333544 mod.declPtr(std_file.root_decl.unwrap().?).src_namespace,
32624 "builtin",
33545 try ip.getOrPutString(gpa, "builtin"),
3262533546 )) orelse @panic("lib/std.zig is corrupt and missing 'builtin'");
3262633547 const builtin_inst = try sema.analyzeLoad(&block, src, opt_builtin_inst, src);
3262733548 const builtin_ty = sema.analyzeAsType(&block, src, builtin_inst) catch |err| switch (err) {
......@@ -32631,8 +33552,8 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
3263133552 const opt_ty_decl = (try sema.namespaceLookup(
3263233553 &block,
3263333554 src,
32634 builtin_ty.getNamespace().?,
32635 name,
33555 builtin_ty.getNamespaceIndex(mod).unwrap().?,
33556 try ip.getOrPutString(gpa, name),
3263633557 )) orelse std.debug.panic("lib/std/builtin.zig is corrupt and missing '{s}'", .{name});
3263733558 return sema.analyzeDeclVal(&block, src, opt_ty_decl);
3263833559}
......@@ -32640,7 +33561,7 @@ fn getBuiltin(sema: *Sema, name: []const u8) CompileError!Air.Inst.Ref {
3264033561fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
3264133562 const ty_inst = try sema.getBuiltin(name);
3264233563
32643 var wip_captures = try WipCaptureScope.init(sema.gpa, sema.perm_arena, sema.owner_decl.src_scope);
33564 var wip_captures = try WipCaptureScope.init(sema.gpa, sema.owner_decl.src_scope);
3264433565 defer wip_captures.deinit();
3264533566
3264633567 var block: Block = .{
......@@ -32673,341 +33594,287 @@ fn getBuiltinType(sema: *Sema, name: []const u8) CompileError!Type {
3267333594/// that the types are already resolved.
3267433595/// TODO assert the return value matches `ty.onePossibleValue`
3267533596pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
32676 switch (ty.tag()) {
32677 .f16,
32678 .f32,
32679 .f64,
32680 .f80,
32681 .f128,
32682 .c_longdouble,
32683 .comptime_int,
32684 .comptime_float,
32685 .u1,
32686 .u8,
32687 .i8,
32688 .u16,
32689 .i16,
32690 .u29,
32691 .u32,
32692 .i32,
32693 .u64,
32694 .i64,
32695 .u128,
32696 .i128,
32697 .usize,
32698 .isize,
32699 .c_char,
32700 .c_short,
32701 .c_ushort,
32702 .c_int,
32703 .c_uint,
32704 .c_long,
32705 .c_ulong,
32706 .c_longlong,
32707 .c_ulonglong,
32708 .bool,
32709 .type,
32710 .anyerror,
32711 .error_set_single,
32712 .error_set,
32713 .error_set_merged,
32714 .error_union,
32715 .fn_noreturn_no_args,
32716 .fn_void_no_args,
32717 .fn_naked_noreturn_no_args,
32718 .fn_ccc_void_no_args,
32719 .function,
32720 .single_const_pointer_to_comptime_int,
32721 .array_sentinel,
32722 .array_u8_sentinel_0,
32723 .const_slice_u8,
32724 .const_slice_u8_sentinel_0,
32725 .const_slice,
32726 .mut_slice,
32727 .anyopaque,
32728 .optional_single_mut_pointer,
32729 .optional_single_const_pointer,
32730 .enum_literal,
32731 .anyerror_void_error_union,
32732 .error_set_inferred,
32733 .@"opaque",
32734 .manyptr_u8,
32735 .manyptr_const_u8,
32736 .manyptr_const_u8_sentinel_0,
32737 .atomic_order,
32738 .atomic_rmw_op,
32739 .calling_convention,
32740 .address_space,
32741 .float_mode,
32742 .reduce_op,
32743 .modifier,
32744 .prefetch_options,
32745 .export_options,
32746 .extern_options,
32747 .type_info,
32748 .@"anyframe",
32749 .anyframe_T,
32750 .many_const_pointer,
32751 .many_mut_pointer,
32752 .c_const_pointer,
32753 .c_mut_pointer,
32754 .single_const_pointer,
32755 .single_mut_pointer,
32756 .pointer,
32757 => return null,
32758
32759 .optional => {
32760 var buf: Type.Payload.ElemType = undefined;
32761 const child_ty = ty.optionalChild(&buf);
32762 if (child_ty.isNoReturn()) {
32763 return Value.null;
32764 } else {
33597 const mod = sema.mod;
33598 return switch (ty.toIntern()) {
33599 .empty_struct_type => Value.empty_struct,
33600 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
33601 .int_type => |int_type| {
33602 if (int_type.bits == 0) {
33603 return try mod.intValue(ty, 0);
33604 } else {
33605 return null;
33606 }
33607 },
33608
33609 .ptr_type,
33610 .error_union_type,
33611 .func_type,
33612 .anyframe_type,
33613 .error_set_type,
33614 .inferred_error_set_type,
33615 => null,
33616
33617 inline .array_type, .vector_type => |seq_type, seq_tag| {
33618 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
33619 if (seq_type.len + @boolToInt(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
33620 .ty = ty.toIntern(),
33621 .storage = .{ .elems = &.{} },
33622 } })).toValue();
33623
33624 if (try sema.typeHasOnePossibleValue(seq_type.child.toType())) |opv| {
33625 return (try mod.intern(.{ .aggregate = .{
33626 .ty = ty.toIntern(),
33627 .storage = .{ .repeated_elem = opv.toIntern() },
33628 } })).toValue();
33629 }
3276533630 return null;
32766 }
32767 },
33631 },
33632 .opt_type => |child| {
33633 if (child == .noreturn_type) {
33634 return try mod.nullValue(ty);
33635 } else {
33636 return null;
33637 }
33638 },
3276833639
32769 .@"struct" => {
32770 const resolved_ty = try sema.resolveTypeFields(ty);
32771 const s = resolved_ty.castTag(.@"struct").?.data;
32772 for (s.fields.values(), 0..) |field, i| {
32773 if (field.is_comptime) continue;
32774 if (field.ty.eql(resolved_ty, sema.mod)) {
33640 .simple_type => |t| switch (t) {
33641 .f16,
33642 .f32,
33643 .f64,
33644 .f80,
33645 .f128,
33646 .usize,
33647 .isize,
33648 .c_char,
33649 .c_short,
33650 .c_ushort,
33651 .c_int,
33652 .c_uint,
33653 .c_long,
33654 .c_ulong,
33655 .c_longlong,
33656 .c_ulonglong,
33657 .c_longdouble,
33658 .anyopaque,
33659 .bool,
33660 .type,
33661 .anyerror,
33662 .comptime_int,
33663 .comptime_float,
33664 .enum_literal,
33665 .atomic_order,
33666 .atomic_rmw_op,
33667 .calling_convention,
33668 .address_space,
33669 .float_mode,
33670 .reduce_op,
33671 .call_modifier,
33672 .prefetch_options,
33673 .export_options,
33674 .extern_options,
33675 .type_info,
33676 => null,
33677
33678 .void => Value.void,
33679 .noreturn => Value.@"unreachable",
33680 .null => Value.null,
33681 .undefined => Value.undef,
33682
33683 .generic_poison => return error.GenericPoison,
33684 },
33685 .struct_type => |struct_type| {
33686 const resolved_ty = try sema.resolveTypeFields(ty);
33687 if (mod.structPtrUnwrap(struct_type.index)) |s| {
33688 const field_vals = try sema.arena.alloc(InternPool.Index, s.fields.count());
33689 for (field_vals, s.fields.values(), 0..) |*field_val, field, i| {
33690 if (field.is_comptime) {
33691 field_val.* = field.default_val;
33692 continue;
33693 }
33694 if (field.ty.eql(resolved_ty, sema.mod)) {
33695 const msg = try Module.ErrorMsg.create(
33696 sema.gpa,
33697 s.srcLoc(sema.mod),
33698 "struct '{}' depends on itself",
33699 .{ty.fmt(sema.mod)},
33700 );
33701 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33702 return sema.failWithOwnedErrorMsg(msg);
33703 }
33704 if (try sema.typeHasOnePossibleValue(field.ty)) |field_opv| {
33705 field_val.* = try field_opv.intern(field.ty, mod);
33706 } else return null;
33707 }
33708
33709 // In this case the struct has no runtime-known fields and
33710 // therefore has one possible value.
33711 return (try mod.intern(.{ .aggregate = .{
33712 .ty = ty.toIntern(),
33713 .storage = .{ .elems = field_vals },
33714 } })).toValue();
33715 }
33716
33717 // In this case the struct has no fields at all and
33718 // therefore has one possible value.
33719 return (try mod.intern(.{ .aggregate = .{
33720 .ty = ty.toIntern(),
33721 .storage = .{ .elems = &.{} },
33722 } })).toValue();
33723 },
33724
33725 .anon_struct_type => |tuple| {
33726 for (tuple.values) |val| {
33727 if (val == .none) return null;
33728 }
33729 // In this case the struct has all comptime-known fields and
33730 // therefore has one possible value.
33731 // TODO: write something like getCoercedInts to avoid needing to dupe
33732 return (try mod.intern(.{ .aggregate = .{
33733 .ty = ty.toIntern(),
33734 .storage = .{ .elems = try sema.arena.dupe(InternPool.Index, tuple.values) },
33735 } })).toValue();
33736 },
33737
33738 .union_type => |union_type| {
33739 const resolved_ty = try sema.resolveTypeFields(ty);
33740 const union_obj = mod.unionPtr(union_type.index);
33741 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
33742 return null;
33743 const fields = union_obj.fields.values();
33744 if (fields.len == 0) {
33745 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
33746 return only.toValue();
33747 }
33748 const only_field = fields[0];
33749 if (only_field.ty.eql(resolved_ty, sema.mod)) {
3277533750 const msg = try Module.ErrorMsg.create(
3277633751 sema.gpa,
32777 s.srcLoc(sema.mod),
32778 "struct '{}' depends on itself",
33752 union_obj.srcLoc(sema.mod),
33753 "union '{}' depends on itself",
3277933754 .{ty.fmt(sema.mod)},
3278033755 );
32781 try sema.addFieldErrNote(resolved_ty, i, msg, "while checking this field", .{});
33756 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
3278233757 return sema.failWithOwnedErrorMsg(msg);
3278333758 }
32784 if ((try sema.typeHasOnePossibleValue(field.ty)) == null) {
33759 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
3278533760 return null;
32786 }
32787 }
32788 return Value.initTag(.empty_struct_value);
32789 },
32790
32791 .tuple, .anon_struct => {
32792 const tuple = ty.tupleFields();
32793 for (tuple.values, 0..) |val, i| {
32794 const is_comptime = val.tag() != .unreachable_value;
32795 if (is_comptime) continue;
32796 if ((try sema.typeHasOnePossibleValue(tuple.types[i])) != null) continue;
32797 return null;
32798 }
32799 return Value.initTag(.empty_struct_value);
32800 },
33761 const only = try mod.intern(.{ .un = .{
33762 .ty = resolved_ty.toIntern(),
33763 .tag = tag_val.toIntern(),
33764 .val = val_val.toIntern(),
33765 } });
33766 return only.toValue();
33767 },
33768 .opaque_type => null,
33769 .enum_type => |enum_type| switch (enum_type.tag_mode) {
33770 .nonexhaustive => {
33771 if (enum_type.tag_ty == .comptime_int_type) return null;
33772
33773 if (try sema.typeHasOnePossibleValue(enum_type.tag_ty.toType())) |int_opv| {
33774 const only = try mod.intern(.{ .enum_tag = .{
33775 .ty = ty.toIntern(),
33776 .int = int_opv.toIntern(),
33777 } });
33778 return only.toValue();
33779 }
3280133780
32802 .enum_numbered => {
32803 const resolved_ty = try sema.resolveTypeFields(ty);
32804 const enum_obj = resolved_ty.castTag(.enum_numbered).?.data;
32805 // An explicit tag type is always provided for enum_numbered.
32806 if (enum_obj.tag_ty.hasRuntimeBits()) {
32807 return null;
32808 }
32809 if (enum_obj.fields.count() == 1) {
32810 if (enum_obj.values.count() == 0) {
32811 return Value.zero; // auto-numbered
32812 } else {
32813 return enum_obj.values.keys()[0];
32814 }
32815 } else {
32816 return null;
32817 }
32818 },
32819 .enum_full => {
32820 const resolved_ty = try sema.resolveTypeFields(ty);
32821 const enum_obj = resolved_ty.castTag(.enum_full).?.data;
32822 if (enum_obj.tag_ty.hasRuntimeBits()) {
32823 return null;
32824 }
32825 switch (enum_obj.fields.count()) {
32826 0 => return Value.initTag(.unreachable_value),
32827 1 => if (enum_obj.values.count() == 0) {
32828 return Value.zero; // auto-numbered
32829 } else {
32830 return enum_obj.values.keys()[0];
33781 return null;
3283133782 },
32832 else => return null,
32833 }
32834 },
32835 .enum_simple => {
32836 const resolved_ty = try sema.resolveTypeFields(ty);
32837 const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
32838 switch (enum_simple.fields.count()) {
32839 0 => return Value.initTag(.unreachable_value),
32840 1 => return Value.zero,
32841 else => return null,
32842 }
32843 },
32844 .enum_nonexhaustive => {
32845 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
32846 if (tag_ty.zigTypeTag() != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) {
32847 return Value.zero;
32848 } else {
32849 return null;
32850 }
32851 },
32852 .@"union", .union_safety_tagged, .union_tagged => {
32853 const resolved_ty = try sema.resolveTypeFields(ty);
32854 const union_obj = resolved_ty.cast(Type.Payload.Union).?.data;
32855 const tag_val = (try sema.typeHasOnePossibleValue(union_obj.tag_ty)) orelse
32856 return null;
32857 const fields = union_obj.fields.values();
32858 if (fields.len == 0) return Value.initTag(.unreachable_value);
32859 const only_field = fields[0];
32860 if (only_field.ty.eql(resolved_ty, sema.mod)) {
32861 const msg = try Module.ErrorMsg.create(
32862 sema.gpa,
32863 union_obj.srcLoc(sema.mod),
32864 "union '{}' depends on itself",
32865 .{ty.fmt(sema.mod)},
32866 );
32867 try sema.addFieldErrNote(resolved_ty, 0, msg, "while checking this field", .{});
32868 return sema.failWithOwnedErrorMsg(msg);
32869 }
32870 const val_val = (try sema.typeHasOnePossibleValue(only_field.ty)) orelse
32871 return null;
32872 // TODO make this not allocate. The function in `Type.onePossibleValue`
32873 // currently returns `empty_struct_value` and we should do that here too.
32874 return try Value.Tag.@"union".create(sema.arena, .{
32875 .tag = tag_val,
32876 .val = val_val,
32877 });
32878 },
33783 .auto, .explicit => {
33784 if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
3287933785
32880 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
32881 .void => return Value.void,
32882 .noreturn => return Value.initTag(.unreachable_value),
32883 .null => return Value.null,
32884 .undefined => return Value.initTag(.undef),
33786 switch (enum_type.names.len) {
33787 0 => {
33788 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
33789 return only.toValue();
33790 },
33791 1 => return try mod.getCoerced((if (enum_type.values.len == 0)
33792 try mod.intern(.{ .int = .{
33793 .ty = enum_type.tag_ty,
33794 .storage = .{ .u64 = 0 },
33795 } })
33796 else
33797 enum_type.values[0]).toValue(), ty),
33798 else => return null,
33799 }
33800 },
33801 },
3288533802
32886 .int_unsigned, .int_signed => {
32887 if (ty.cast(Type.Payload.Bits).?.data == 0) {
32888 return Value.zero;
32889 } else {
32890 return null;
32891 }
32892 },
32893 .vector, .array, .array_u8 => {
32894 if (ty.arrayLen() == 0)
32895 return Value.initTag(.empty_array);
32896 if ((try sema.typeHasOnePossibleValue(ty.elemType())) != null) {
32897 return Value.initTag(.the_only_possible_value);
32898 }
32899 return null;
33803 // values, not types
33804 .undef,
33805 .runtime_value,
33806 .simple_value,
33807 .variable,
33808 .extern_func,
33809 .func,
33810 .int,
33811 .err,
33812 .error_union,
33813 .enum_literal,
33814 .enum_tag,
33815 .empty_enum_value,
33816 .float,
33817 .ptr,
33818 .opt,
33819 .aggregate,
33820 .un,
33821 // memoization, not types
33822 .memoized_call,
33823 => unreachable,
3290033824 },
32901
32902 .inferred_alloc_const => unreachable,
32903 .inferred_alloc_mut => unreachable,
32904 .generic_poison => return error.GenericPoison,
32905 }
33825 };
3290633826}
3290733827
3290833828/// Returns the type of the AIR instruction.
3290933829fn typeOf(sema: *Sema, inst: Air.Inst.Ref) Type {
32910 return sema.getTmpAir().typeOf(inst);
33830 return sema.getTmpAir().typeOf(inst, &sema.mod.intern_pool);
3291133831}
3291233832
3291333833pub fn getTmpAir(sema: Sema) Air {
3291433834 return .{
3291533835 .instructions = sema.air_instructions.slice(),
3291633836 .extra = sema.air_extra.items,
32917 .values = sema.air_values.items,
3291833837 };
3291933838}
3292033839
3292133840pub fn addType(sema: *Sema, ty: Type) !Air.Inst.Ref {
32922 switch (ty.tag()) {
32923 .u1 => return .u1_type,
32924 .u8 => return .u8_type,
32925 .i8 => return .i8_type,
32926 .u16 => return .u16_type,
32927 .u29 => return .u29_type,
32928 .i16 => return .i16_type,
32929 .u32 => return .u32_type,
32930 .i32 => return .i32_type,
32931 .u64 => return .u64_type,
32932 .i64 => return .i64_type,
32933 .u128 => return .u128_type,
32934 .i128 => return .i128_type,
32935 .usize => return .usize_type,
32936 .isize => return .isize_type,
32937 .c_short => return .c_short_type,
32938 .c_ushort => return .c_ushort_type,
32939 .c_int => return .c_int_type,
32940 .c_uint => return .c_uint_type,
32941 .c_long => return .c_long_type,
32942 .c_ulong => return .c_ulong_type,
32943 .c_longlong => return .c_longlong_type,
32944 .c_ulonglong => return .c_ulonglong_type,
32945 .c_longdouble => return .c_longdouble_type,
32946 .f16 => return .f16_type,
32947 .f32 => return .f32_type,
32948 .f64 => return .f64_type,
32949 .f80 => return .f80_type,
32950 .f128 => return .f128_type,
32951 .anyopaque => return .anyopaque_type,
32952 .bool => return .bool_type,
32953 .void => return .void_type,
32954 .type => return .type_type,
32955 .anyerror => return .anyerror_type,
32956 .comptime_int => return .comptime_int_type,
32957 .comptime_float => return .comptime_float_type,
32958 .noreturn => return .noreturn_type,
32959 .@"anyframe" => return .anyframe_type,
32960 .null => return .null_type,
32961 .undefined => return .undefined_type,
32962 .enum_literal => return .enum_literal_type,
32963 .atomic_order => return .atomic_order_type,
32964 .atomic_rmw_op => return .atomic_rmw_op_type,
32965 .calling_convention => return .calling_convention_type,
32966 .address_space => return .address_space_type,
32967 .float_mode => return .float_mode_type,
32968 .reduce_op => return .reduce_op_type,
32969 .modifier => return .modifier_type,
32970 .prefetch_options => return .prefetch_options_type,
32971 .export_options => return .export_options_type,
32972 .extern_options => return .extern_options_type,
32973 .type_info => return .type_info_type,
32974 .manyptr_u8 => return .manyptr_u8_type,
32975 .manyptr_const_u8 => return .manyptr_const_u8_type,
32976 .fn_noreturn_no_args => return .fn_noreturn_no_args_type,
32977 .fn_void_no_args => return .fn_void_no_args_type,
32978 .fn_naked_noreturn_no_args => return .fn_naked_noreturn_no_args_type,
32979 .fn_ccc_void_no_args => return .fn_ccc_void_no_args_type,
32980 .single_const_pointer_to_comptime_int => return .single_const_pointer_to_comptime_int_type,
32981 .const_slice_u8 => return .const_slice_u8_type,
32982 .anyerror_void_error_union => return .anyerror_void_error_union_type,
32983 .generic_poison => return .generic_poison_type,
32984 else => {},
32985 }
33841 if (@enumToInt(ty.toIntern()) < Air.ref_start_index)
33842 return @intToEnum(Air.Inst.Ref, @enumToInt(ty.toIntern()));
3298633843 try sema.air_instructions.append(sema.gpa, .{
32987 .tag = .const_ty,
32988 .data = .{ .ty = ty },
33844 .tag = .interned,
33845 .data = .{ .interned = ty.toIntern() },
3298933846 });
3299033847 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
3299133848}
3299233849
3299333850fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref {
32994 return sema.addConstant(ty, try Value.Tag.int_u64.create(sema.arena, int));
33851 const mod = sema.mod;
33852 return sema.addConstant(ty, try mod.intValue(ty, int));
3299533853}
3299633854
3299733855fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref {
32998 return sema.addConstant(ty, Value.undef);
33856 return sema.addConstant(ty, (try sema.mod.intern(.{ .undef = ty.toIntern() })).toValue());
3299933857}
3300033858
3300133859pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref {
33860 const mod = sema.mod;
3300233861 const gpa = sema.gpa;
33003 const ty_inst = try sema.addType(ty);
33004 try sema.air_values.append(gpa, val);
33862
33863 // This assertion can be removed when the `ty` parameter is removed from
33864 // this function thanks to the InternPool transition being complete.
33865 if (std.debug.runtime_safety) {
33866 const val_ty = mod.intern_pool.typeOf(val.toIntern());
33867 if (ty.toIntern() != val_ty) {
33868 std.debug.panic("addConstant type mismatch: '{}' vs '{}'\n", .{
33869 ty.fmt(mod), val_ty.toType().fmt(mod),
33870 });
33871 }
33872 }
33873 if (@enumToInt(val.toIntern()) < Air.ref_start_index)
33874 return @intToEnum(Air.Inst.Ref, @enumToInt(val.toIntern()));
3300533875 try sema.air_instructions.append(gpa, .{
33006 .tag = .constant,
33007 .data = .{ .ty_pl = .{
33008 .ty = ty_inst,
33009 .payload = @intCast(u32, sema.air_values.items.len - 1),
33010 } },
33876 .tag = .interned,
33877 .data = .{ .interned = val.toIntern() },
3301133878 });
3301233879 return Air.indexToRef(@intCast(u32, sema.air_instructions.len - 1));
3301333880}
......@@ -33026,7 +33893,8 @@ pub fn addExtraAssumeCapacity(sema: *Sema, extra: anytype) u32 {
3302633893 u32 => @field(extra, field.name),
3302733894 Air.Inst.Ref => @enumToInt(@field(extra, field.name)),
3302833895 i32 => @bitCast(u32, @field(extra, field.name)),
33029 else => @compileError("bad field type"),
33896 InternPool.Index => @enumToInt(@field(extra, field.name)),
33897 else => @compileError("bad field type: " ++ @typeName(field.type)),
3303033898 });
3303133899 }
3303233900 return result;
......@@ -33072,21 +33940,25 @@ fn analyzeComptimeAlloc(
3307233940 defer anon_decl.deinit();
3307333941
3307433942 const decl_index = try anon_decl.finish(
33075 try var_type.copy(anon_decl.arena()),
33943 var_type,
3307633944 // There will be stores before the first load, but they may be to sub-elements or
3307733945 // sub-fields. So we need to initialize with undef to allow the mechanism to expand
3307833946 // into fields/elements and have those overridden with stored values.
33079 Value.undef,
33947 (try sema.mod.intern(.{ .undef = var_type.toIntern() })).toValue(),
3308033948 alignment,
3308133949 );
3308233950 const decl = sema.mod.declPtr(decl_index);
3308333951 decl.@"align" = alignment;
3308433952
33953 try sema.comptime_mutable_decls.append(decl_index);
3308533954 try sema.mod.declareDeclDependency(sema.owner_decl_index, decl_index);
33086 return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{
33087 .runtime_index = block.runtime_index,
33088 .decl_index = decl_index,
33089 }));
33955 return sema.addConstant(ptr_type, (try sema.mod.intern(.{ .ptr = .{
33956 .ty = ptr_type.toIntern(),
33957 .addr = .{ .mut_decl = .{
33958 .decl = decl_index,
33959 .runtime_index = block.runtime_index,
33960 } },
33961 } })).toValue());
3309033962}
3309133963
3309233964/// The places where a user can specify an address space attribute
......@@ -33114,8 +33986,9 @@ pub fn analyzeAddressSpace(
3311433986 zir_ref: Zir.Inst.Ref,
3311533987 ctx: AddressSpaceContext,
3311633988) !std.builtin.AddressSpace {
33989 const mod = sema.mod;
3311733990 const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref, "addresspace must be comptime-known");
33118 const address_space = addrspace_tv.val.toEnum(std.builtin.AddressSpace);
33991 const address_space = mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
3311933992 const target = sema.mod.getTarget();
3312033993 const arch = target.cpu.arch;
3312133994
......@@ -33158,8 +34031,9 @@ pub fn analyzeAddressSpace(
3315834031/// Asserts the value is a pointer and dereferences it.
3315934032/// Returns `null` if the pointer contents cannot be loaded at comptime.
3316034033fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr_ty: Type) CompileError!?Value {
33161 const load_ty = ptr_ty.childType();
33162 const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty, true);
34034 const mod = sema.mod;
34035 const load_ty = ptr_ty.childType(mod);
34036 const res = try sema.pointerDerefExtra(block, src, ptr_val, load_ty);
3316334037 switch (res) {
3316434038 .runtime_load => return null,
3316534039 .val => |v| return v,
......@@ -33185,8 +34059,9 @@ const DerefResult = union(enum) {
3318534059 out_of_bounds: Type,
3318634060};
3318734061
33188fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type, want_mutable: bool) CompileError!DerefResult {
33189 const target = sema.mod.getTarget();
34062fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, load_ty: Type) CompileError!DerefResult {
34063 const mod = sema.mod;
34064 const target = mod.getTarget();
3319034065 const deref = sema.beginComptimePtrLoad(block, src, ptr_val, load_ty) catch |err| switch (err) {
3319134066 error.RuntimeLoad => return DerefResult{ .runtime_load = {} },
3319234067 else => |e| return e,
......@@ -33199,19 +34074,17 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value
3319934074 if (coerce_in_mem_ok) {
3320034075 // We have a Value that lines up in virtual memory exactly with what we want to load,
3320134076 // and it is in-memory coercible to load_ty. It may be returned without modifications.
33202 if (deref.is_mutable and want_mutable) {
33203 // The decl whose value we are obtaining here may be overwritten with
33204 // a different value upon further semantic analysis, which would
33205 // invalidate this memory. So we must copy here.
33206 return DerefResult{ .val = try tv.val.copy(sema.arena) };
33207 }
33208 return DerefResult{ .val = tv.val };
34077 // Move mutable decl values to the InternPool and assert other decls are already in
34078 // the InternPool.
34079 const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern();
34080 const coerced_val = try sema.coerceValueInMemory(block, uncoerced_val.toValue(), tv.ty, load_ty, src);
34081 return .{ .val = coerced_val };
3320934082 }
3321034083 }
3321134084
3321234085 // The type is not in-memory coercible or the direct dereference failed, so it must
3321334086 // be bitcast according to the pointer type we are performing the load through.
33214 if (!load_ty.hasWellDefinedLayout()) {
34087 if (!load_ty.hasWellDefinedLayout(mod)) {
3321534088 return DerefResult{ .needed_well_defined = load_ty };
3321634089 }
3321734090
......@@ -33248,59 +34121,32 @@ fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError
3324834121/// This can return `error.AnalysisFail` because it sometimes requires resolving whether
3324934122/// a type has zero bits, which can cause a "foo depends on itself" compile error.
3325034123/// This logic must be kept in sync with `Type.isPtrLikeOptional`.
33251fn typePtrOrOptionalPtrTy(
33252 sema: *Sema,
33253 ty: Type,
33254 buf: *Type.Payload.ElemType,
33255) !?Type {
33256 switch (ty.tag()) {
33257 .optional_single_const_pointer,
33258 .optional_single_mut_pointer,
33259 .c_const_pointer,
33260 .c_mut_pointer,
33261 => return ty.optionalChild(buf),
33262
33263 .single_const_pointer_to_comptime_int,
33264 .single_const_pointer,
33265 .single_mut_pointer,
33266 .many_const_pointer,
33267 .many_mut_pointer,
33268 .manyptr_u8,
33269 .manyptr_const_u8,
33270 .manyptr_const_u8_sentinel_0,
33271 => return ty,
33272
33273 .pointer => switch (ty.ptrSize()) {
33274 .Slice => return null,
33275 .C => return ty.optionalChild(buf),
33276 else => return ty,
33277 },
33278
33279 .inferred_alloc_const => unreachable,
33280 .inferred_alloc_mut => unreachable,
33281
33282 .optional => {
33283 const child_type = ty.optionalChild(buf);
33284 if (child_type.zigTypeTag() != .Pointer) return null;
33285
33286 const info = child_type.ptrInfo().data;
33287 switch (info.size) {
33288 .Slice, .C => return null,
34124fn typePtrOrOptionalPtrTy(sema: *Sema, ty: Type) !?Type {
34125 const mod = sema.mod;
34126 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
34127 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
34128 .One, .Many, .C => ty,
34129 .Slice => null,
34130 },
34131 .opt_type => |opt_child| switch (mod.intern_pool.indexToKey(opt_child)) {
34132 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
34133 .Slice, .C => null,
3328934134 .Many, .One => {
33290 if (info.@"allowzero") return null;
34135 if (ptr_type.flags.is_allowzero) return null;
3329134136
3329234137 // optionals of zero sized types behave like bools, not pointers
33293 if ((try sema.typeHasOnePossibleValue(child_type)) != null) {
34138 const payload_ty = opt_child.toType();
34139 if ((try sema.typeHasOnePossibleValue(payload_ty)) != null) {
3329434140 return null;
3329534141 }
3329634142
33297 return child_type;
34143 return payload_ty;
3329834144 },
33299 }
34145 },
34146 else => null,
3330034147 },
33301
33302 else => return null,
33303 }
34148 else => null,
34149 };
3330434150}
3330534151
3330634152/// `generic_poison` will return false.
......@@ -33310,201 +34156,170 @@ fn typePtrOrOptionalPtrTy(
3331034156/// TODO merge these implementations together with the "advanced"/opt_sema pattern seen
3331134157/// elsewhere in value.zig
3331234158pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
33313 return switch (ty.tag()) {
33314 .u1,
33315 .u8,
33316 .i8,
33317 .u16,
33318 .i16,
33319 .u29,
33320 .u32,
33321 .i32,
33322 .u64,
33323 .i64,
33324 .u128,
33325 .i128,
33326 .usize,
33327 .isize,
33328 .c_char,
33329 .c_short,
33330 .c_ushort,
33331 .c_int,
33332 .c_uint,
33333 .c_long,
33334 .c_ulong,
33335 .c_longlong,
33336 .c_ulonglong,
33337 .c_longdouble,
33338 .f16,
33339 .f32,
33340 .f64,
33341 .f80,
33342 .f128,
33343 .anyopaque,
33344 .bool,
33345 .void,
33346 .anyerror,
33347 .noreturn,
33348 .@"anyframe",
33349 .null,
33350 .undefined,
33351 .atomic_order,
33352 .atomic_rmw_op,
33353 .calling_convention,
33354 .address_space,
33355 .float_mode,
33356 .reduce_op,
33357 .modifier,
33358 .prefetch_options,
33359 .export_options,
33360 .extern_options,
33361 .manyptr_u8,
33362 .manyptr_const_u8,
33363 .manyptr_const_u8_sentinel_0,
33364 .const_slice_u8,
33365 .const_slice_u8_sentinel_0,
33366 .anyerror_void_error_union,
33367 .empty_struct_literal,
33368 .empty_struct,
33369 .error_set,
33370 .error_set_single,
33371 .error_set_inferred,
33372 .error_set_merged,
33373 .@"opaque",
33374 .generic_poison,
33375 .array_u8,
33376 .array_u8_sentinel_0,
33377 .int_signed,
33378 .int_unsigned,
33379 .enum_simple,
33380 => false,
33381
33382 .single_const_pointer_to_comptime_int,
33383 .type,
33384 .comptime_int,
33385 .comptime_float,
33386 .enum_literal,
33387 .type_info,
33388 // These are function bodies, not function pointers.
33389 .fn_noreturn_no_args,
33390 .fn_void_no_args,
33391 .fn_naked_noreturn_no_args,
33392 .fn_ccc_void_no_args,
33393 .function,
33394 => true,
33395
33396 .inferred_alloc_mut => unreachable,
33397 .inferred_alloc_const => unreachable,
33398
33399 .array,
33400 .array_sentinel,
33401 .vector,
33402 => return sema.typeRequiresComptime(ty.childType()),
33403
33404 .pointer,
33405 .single_const_pointer,
33406 .single_mut_pointer,
33407 .many_const_pointer,
33408 .many_mut_pointer,
33409 .c_const_pointer,
33410 .c_mut_pointer,
33411 .const_slice,
33412 .mut_slice,
33413 => {
33414 const child_ty = ty.childType();
33415 if (child_ty.zigTypeTag() == .Fn) {
33416 return child_ty.fnInfo().is_generic;
33417 } else {
33418 return sema.typeRequiresComptime(child_ty);
33419 }
33420 },
33421
33422 .optional,
33423 .optional_single_mut_pointer,
33424 .optional_single_const_pointer,
33425 => {
33426 var buf: Type.Payload.ElemType = undefined;
33427 return sema.typeRequiresComptime(ty.optionalChild(&buf));
33428 },
33429
33430 .tuple, .anon_struct => {
33431 const tuple = ty.tupleFields();
33432 for (tuple.types, 0..) |field_ty, i| {
33433 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
33434 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty)) {
33435 return true;
34159 const mod = sema.mod;
34160 return switch (ty.toIntern()) {
34161 .empty_struct_type => false,
34162
34163 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
34164 .int_type => return false,
34165 .ptr_type => |ptr_type| {
34166 const child_ty = ptr_type.child.toType();
34167 if (child_ty.zigTypeTag(mod) == .Fn) {
34168 return mod.typeToFunc(child_ty).?.is_generic;
34169 } else {
34170 return sema.typeRequiresComptime(child_ty);
3343634171 }
33437 }
33438 return false;
33439 },
33440
33441 .@"struct" => {
33442 const struct_obj = ty.castTag(.@"struct").?.data;
33443 switch (struct_obj.requires_comptime) {
33444 .no, .wip => return false,
33445 .yes => return true,
33446 .unknown => {
33447 if (struct_obj.status == .field_types_wip)
33448 return false;
34172 },
34173 .anyframe_type => |child| {
34174 if (child == .none) return false;
34175 return sema.typeRequiresComptime(child.toType());
34176 },
34177 .array_type => |array_type| return sema.typeRequiresComptime(array_type.child.toType()),
34178 .vector_type => |vector_type| return sema.typeRequiresComptime(vector_type.child.toType()),
34179 .opt_type => |child| return sema.typeRequiresComptime(child.toType()),
3344934180
33450 try sema.resolveTypeFieldsStruct(ty, struct_obj);
34181 .error_union_type => |error_union_type| {
34182 return sema.typeRequiresComptime(error_union_type.payload_type.toType());
34183 },
3345134184
33452 struct_obj.requires_comptime = .wip;
33453 for (struct_obj.fields.values()) |field| {
33454 if (field.is_comptime) continue;
33455 if (try sema.typeRequiresComptime(field.ty)) {
33456 struct_obj.requires_comptime = .yes;
33457 return true;
34185 .error_set_type, .inferred_error_set_type => false,
34186
34187 .func_type => true,
34188
34189 .simple_type => |t| return switch (t) {
34190 .f16,
34191 .f32,
34192 .f64,
34193 .f80,
34194 .f128,
34195 .usize,
34196 .isize,
34197 .c_char,
34198 .c_short,
34199 .c_ushort,
34200 .c_int,
34201 .c_uint,
34202 .c_long,
34203 .c_ulong,
34204 .c_longlong,
34205 .c_ulonglong,
34206 .c_longdouble,
34207 .anyopaque,
34208 .bool,
34209 .void,
34210 .anyerror,
34211 .noreturn,
34212 .generic_poison,
34213 .atomic_order,
34214 .atomic_rmw_op,
34215 .calling_convention,
34216 .address_space,
34217 .float_mode,
34218 .reduce_op,
34219 .call_modifier,
34220 .prefetch_options,
34221 .export_options,
34222 .extern_options,
34223 => false,
34224
34225 .type,
34226 .comptime_int,
34227 .comptime_float,
34228 .null,
34229 .undefined,
34230 .enum_literal,
34231 .type_info,
34232 => true,
34233 },
34234 .struct_type => |struct_type| {
34235 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
34236 switch (struct_obj.requires_comptime) {
34237 .no, .wip => return false,
34238 .yes => return true,
34239 .unknown => {
34240 if (struct_obj.status == .field_types_wip)
34241 return false;
34242
34243 try sema.resolveTypeFieldsStruct(ty, struct_obj);
34244
34245 struct_obj.requires_comptime = .wip;
34246 for (struct_obj.fields.values()) |field| {
34247 if (field.is_comptime) continue;
34248 if (try sema.typeRequiresComptime(field.ty)) {
34249 struct_obj.requires_comptime = .yes;
34250 return true;
34251 }
3345834252 }
33459 }
33460 struct_obj.requires_comptime = .no;
33461 return false;
33462 },
33463 }
33464 },
33465
33466 .@"union", .union_safety_tagged, .union_tagged => {
33467 const union_obj = ty.cast(Type.Payload.Union).?.data;
33468 switch (union_obj.requires_comptime) {
33469 .no, .wip => return false,
33470 .yes => return true,
33471 .unknown => {
33472 if (union_obj.status == .field_types_wip)
34253 struct_obj.requires_comptime = .no;
3347334254 return false;
34255 },
34256 }
34257 },
34258 .anon_struct_type => |tuple| {
34259 for (tuple.types, tuple.values) |field_ty, val| {
34260 const have_comptime_val = val != .none;
34261 if (!have_comptime_val and try sema.typeRequiresComptime(field_ty.toType())) {
34262 return true;
34263 }
34264 }
34265 return false;
34266 },
3347434267
33475 try sema.resolveTypeFieldsUnion(ty, union_obj);
33476
33477 union_obj.requires_comptime = .wip;
33478 for (union_obj.fields.values()) |field| {
33479 if (try sema.typeRequiresComptime(field.ty)) {
33480 union_obj.requires_comptime = .yes;
33481 return true;
34268 .union_type => |union_type| {
34269 const union_obj = mod.unionPtr(union_type.index);
34270 switch (union_obj.requires_comptime) {
34271 .no, .wip => return false,
34272 .yes => return true,
34273 .unknown => {
34274 if (union_obj.status == .field_types_wip)
34275 return false;
34276
34277 try sema.resolveTypeFieldsUnion(ty, union_obj);
34278
34279 union_obj.requires_comptime = .wip;
34280 for (union_obj.fields.values()) |field| {
34281 if (try sema.typeRequiresComptime(field.ty)) {
34282 union_obj.requires_comptime = .yes;
34283 return true;
34284 }
3348234285 }
33483 }
33484 union_obj.requires_comptime = .no;
33485 return false;
33486 },
33487 }
33488 },
34286 union_obj.requires_comptime = .no;
34287 return false;
34288 },
34289 }
34290 },
3348934291
33490 .error_union => return sema.typeRequiresComptime(ty.errorUnionPayload()),
33491 .anyframe_T => {
33492 const child_ty = ty.castTag(.anyframe_T).?.data;
33493 return sema.typeRequiresComptime(child_ty);
33494 },
33495 .enum_numbered => {
33496 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
33497 return sema.typeRequiresComptime(tag_ty);
33498 },
33499 .enum_full, .enum_nonexhaustive => {
33500 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
33501 return sema.typeRequiresComptime(tag_ty);
34292 .opaque_type => false,
34293 .enum_type => |enum_type| try sema.typeRequiresComptime(enum_type.tag_ty.toType()),
34294
34295 // values, not types
34296 .undef,
34297 .runtime_value,
34298 .simple_value,
34299 .variable,
34300 .extern_func,
34301 .func,
34302 .int,
34303 .err,
34304 .error_union,
34305 .enum_literal,
34306 .enum_tag,
34307 .empty_enum_value,
34308 .float,
34309 .ptr,
34310 .opt,
34311 .aggregate,
34312 .un,
34313 // memoization, not types
34314 .memoized_call,
34315 => unreachable,
3350234316 },
3350334317 };
3350434318}
3350534319
3350634320pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
33507 return ty.hasRuntimeBitsAdvanced(false, .{ .sema = sema }) catch |err| switch (err) {
34321 const mod = sema.mod;
34322 return ty.hasRuntimeBitsAdvanced(mod, false, .{ .sema = sema }) catch |err| switch (err) {
3350834323 error.NeedLazy => unreachable,
3350934324 else => |e| return e,
3351034325 };
......@@ -33512,19 +34327,18 @@ pub fn typeHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
3351234327
3351334328fn typeAbiSize(sema: *Sema, ty: Type) !u64 {
3351434329 try sema.resolveTypeLayout(ty);
33515 const target = sema.mod.getTarget();
33516 return ty.abiSize(target);
34330 return ty.abiSize(sema.mod);
3351734331}
3351834332
3351934333fn typeAbiAlignment(sema: *Sema, ty: Type) CompileError!u32 {
33520 const target = sema.mod.getTarget();
33521 return (try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar;
34334 return (try ty.abiAlignmentAdvanced(sema.mod, .{ .sema = sema })).scalar;
3352234335}
3352334336
3352434337/// Not valid to call for packed unions.
3352534338/// Keep implementation in sync with `Module.Union.Field.normalAlignment`.
3352634339fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {
33527 if (field.ty.zigTypeTag() == .NoReturn) {
34340 const mod = sema.mod;
34341 if (field.ty.zigTypeTag(mod) == .NoReturn) {
3352834342 return @as(u32, 0);
3352934343 } else if (field.abi_align == 0) {
3353034344 return sema.typeAbiAlignment(field.ty);
......@@ -33535,7 +34349,8 @@ fn unionFieldAlignment(sema: *Sema, field: Module.Union.Field) !u32 {
3353534349
3353634350/// Synchronize logic with `Type.isFnOrHasRuntimeBits`.
3353734351pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
33538 const fn_info = ty.fnInfo();
34352 const mod = sema.mod;
34353 const fn_info = mod.typeToFunc(ty).?;
3353934354 if (fn_info.is_generic) return false;
3354034355 if (fn_info.is_var_args) return true;
3354134356 switch (fn_info.cc) {
......@@ -33543,7 +34358,7 @@ pub fn fnHasRuntimeBits(sema: *Sema, ty: Type) CompileError!bool {
3354334358 .Inline => return false,
3354434359 else => {},
3354534360 }
33546 if (try sema.typeRequiresComptime(fn_info.return_type)) {
34361 if (try sema.typeRequiresComptime(fn_info.return_type.toType())) {
3354734362 return false;
3354834363 }
3354934364 return true;
......@@ -33553,11 +34368,12 @@ fn unionFieldIndex(
3355334368 sema: *Sema,
3355434369 block: *Block,
3355534370 unresolved_union_ty: Type,
33556 field_name: []const u8,
34371 field_name: InternPool.NullTerminatedString,
3355734372 field_src: LazySrcLoc,
3355834373) !u32 {
34374 const mod = sema.mod;
3355934375 const union_ty = try sema.resolveTypeFields(unresolved_union_ty);
33560 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
34376 const union_obj = mod.typeToUnion(union_ty).?;
3356134377 const field_index_usize = union_obj.fields.getIndex(field_name) orelse
3356234378 return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name);
3356334379 return @intCast(u32, field_index_usize);
......@@ -33567,14 +34383,15 @@ fn structFieldIndex(
3356734383 sema: *Sema,
3356834384 block: *Block,
3356934385 unresolved_struct_ty: Type,
33570 field_name: []const u8,
34386 field_name: InternPool.NullTerminatedString,
3357134387 field_src: LazySrcLoc,
3357234388) !u32 {
34389 const mod = sema.mod;
3357334390 const struct_ty = try sema.resolveTypeFields(unresolved_struct_ty);
33574 if (struct_ty.isAnonStruct()) {
34391 if (struct_ty.isAnonStruct(mod)) {
3357534392 return sema.anonStructFieldIndex(block, struct_ty, field_name, field_src);
3357634393 } else {
33577 const struct_obj = struct_ty.castTag(.@"struct").?.data;
34394 const struct_obj = mod.typeToStruct(struct_ty).?;
3357834395 const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
3357934396 return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
3358034397 return @intCast(u32, field_index_usize);
......@@ -33585,55 +34402,98 @@ fn anonStructFieldIndex(
3358534402 sema: *Sema,
3358634403 block: *Block,
3358734404 struct_ty: Type,
33588 field_name: []const u8,
34405 field_name: InternPool.NullTerminatedString,
3358934406 field_src: LazySrcLoc,
3359034407) !u32 {
33591 const anon_struct = struct_ty.castTag(.anon_struct).?.data;
33592 for (anon_struct.names, 0..) |name, i| {
33593 if (mem.eql(u8, name, field_name)) {
33594 return @intCast(u32, i);
33595 }
34408 const mod = sema.mod;
34409 switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
34410 .anon_struct_type => |anon_struct_type| for (anon_struct_type.names, 0..) |name, i| {
34411 if (name == field_name) return @intCast(u32, i);
34412 },
34413 .struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
34414 for (struct_obj.fields.keys(), 0..) |name, i| {
34415 if (name == field_name) {
34416 return @intCast(u32, i);
34417 }
34418 }
34419 },
34420 else => unreachable,
3359634421 }
33597 return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{
33598 field_name, struct_ty.fmt(sema.mod),
34422 return sema.fail(block, field_src, "no field named '{}' in anonymous struct '{}'", .{
34423 field_name.fmt(&mod.intern_pool), struct_ty.fmt(sema.mod),
3359934424 });
3360034425}
3360134426
3360234427fn queueFullTypeResolution(sema: *Sema, ty: Type) !void {
33603 const inst_ref = try sema.addType(ty);
33604 try sema.types_to_resolve.append(sema.gpa, inst_ref);
34428 try sema.types_to_resolve.put(sema.gpa, ty.toIntern(), {});
34429}
34430
34431/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
34432/// overflow_idx to the vector index the overflow was at (or 0 for a scalar).
34433fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value {
34434 var overflow: usize = undefined;
34435 return sema.intAddInner(lhs, rhs, ty, &overflow) catch |err| switch (err) {
34436 error.Overflow => {
34437 const is_vec = ty.isVector(sema.mod);
34438 overflow_idx.* = if (is_vec) overflow else 0;
34439 const safe_ty = if (is_vec) try sema.mod.vectorType(.{
34440 .len = ty.vectorLen(sema.mod),
34441 .child = .comptime_int_type,
34442 }) else Type.comptime_int;
34443 return sema.intAddInner(lhs, rhs, safe_ty, undefined) catch |err1| switch (err1) {
34444 error.Overflow => unreachable,
34445 else => |e| return e,
34446 };
34447 },
34448 else => |e| return e,
34449 };
3360534450}
3360634451
33607fn intAdd(sema: *Sema, lhs: Value, rhs: Value, ty: Type) !Value {
33608 if (ty.zigTypeTag() == .Vector) {
33609 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
34452fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize) !Value {
34453 const mod = sema.mod;
34454 if (ty.zigTypeTag(mod) == .Vector) {
34455 const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod));
34456 const scalar_ty = ty.scalarType(mod);
3361034457 for (result_data, 0..) |*scalar, i| {
33611 var lhs_buf: Value.ElemValueBuffer = undefined;
33612 var rhs_buf: Value.ElemValueBuffer = undefined;
33613 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
33614 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
33615 scalar.* = try sema.intAddScalar(lhs_elem, rhs_elem);
34458 const lhs_elem = try lhs.elemValue(mod, i);
34459 const rhs_elem = try rhs.elemValue(mod, i);
34460 const val = sema.intAddScalar(lhs_elem, rhs_elem, scalar_ty) catch |err| switch (err) {
34461 error.Overflow => {
34462 overflow_idx.* = i;
34463 return error.Overflow;
34464 },
34465 else => |e| return e,
34466 };
34467 scalar.* = try val.intern(scalar_ty, mod);
3361634468 }
33617 return Value.Tag.aggregate.create(sema.arena, result_data);
34469 return (try mod.intern(.{ .aggregate = .{
34470 .ty = ty.toIntern(),
34471 .storage = .{ .elems = result_data },
34472 } })).toValue();
3361834473 }
33619 return sema.intAddScalar(lhs, rhs);
34474 return sema.intAddScalar(lhs, rhs, ty);
3362034475}
3362134476
33622fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
34477fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
34478 const mod = sema.mod;
34479 if (scalar_ty.toIntern() != .comptime_int_type) {
34480 const res = try sema.intAddWithOverflowScalar(lhs, rhs, scalar_ty);
34481 if (res.overflow_bit.compareAllWithZero(.neq, mod)) return error.Overflow;
34482 return res.wrapped_result;
34483 }
3362334484 // TODO is this a performance issue? maybe we should try the operation without
3362434485 // resorting to BigInt first.
3362534486 var lhs_space: Value.BigIntSpace = undefined;
3362634487 var rhs_space: Value.BigIntSpace = undefined;
33627 const target = sema.mod.getTarget();
33628 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);
33629 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
34488 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
34489 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
3363034490 const limbs = try sema.arena.alloc(
3363134491 std.math.big.Limb,
3363234492 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
3363334493 );
3363434494 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3363534495 result_bigint.add(lhs_bigint, rhs_bigint);
33636 return Value.fromBigInt(sema.arena, result_bigint.toConst());
34496 return mod.intValue_big(scalar_ty, result_bigint.toConst());
3363734497}
3363834498
3363934499/// Supports both floats and ints; handles undefined.
......@@ -33643,55 +34503,87 @@ fn numberAddWrapScalar(
3364334503 rhs: Value,
3364434504 ty: Type,
3364534505) !Value {
33646 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
34506 const mod = sema.mod;
34507 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;
3364734508
33648 if (ty.zigTypeTag() == .ComptimeInt) {
33649 return sema.intAdd(lhs, rhs, ty);
34509 if (ty.zigTypeTag(mod) == .ComptimeInt) {
34510 return sema.intAdd(lhs, rhs, ty, undefined);
3365034511 }
3365134512
3365234513 if (ty.isAnyFloat()) {
33653 return sema.floatAdd(lhs, rhs, ty);
34514 return Value.floatAdd(lhs, rhs, ty, sema.arena, mod);
3365434515 }
3365534516
3365634517 const overflow_result = try sema.intAddWithOverflow(lhs, rhs, ty);
3365734518 return overflow_result.wrapped_result;
3365834519}
3365934520
33660fn intSub(
33661 sema: *Sema,
33662 lhs: Value,
33663 rhs: Value,
33664 ty: Type,
33665) !Value {
33666 if (ty.zigTypeTag() == .Vector) {
33667 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
34521/// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
34522/// overflow_idx to the vector index the overflow was at (or 0 for a scalar).
34523fn intSub(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize) !Value {
34524 var overflow: usize = undefined;
34525 return sema.intSubInner(lhs, rhs, ty, &overflow) catch |err| switch (err) {
34526 error.Overflow => {
34527 const is_vec = ty.isVector(sema.mod);
34528 overflow_idx.* = if (is_vec) overflow else 0;
34529 const safe_ty = if (is_vec) try sema.mod.vectorType(.{
34530 .len = ty.vectorLen(sema.mod),
34531 .child = .comptime_int_type,
34532 }) else Type.comptime_int;
34533 return sema.intSubInner(lhs, rhs, safe_ty, undefined) catch |err1| switch (err1) {
34534 error.Overflow => unreachable,
34535 else => |e| return e,
34536 };
34537 },
34538 else => |e| return e,
34539 };
34540}
34541
34542fn intSubInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize) !Value {
34543 const mod = sema.mod;
34544 if (ty.zigTypeTag(mod) == .Vector) {
34545 const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod));
34546 const scalar_ty = ty.scalarType(mod);
3366834547 for (result_data, 0..) |*scalar, i| {
33669 var lhs_buf: Value.ElemValueBuffer = undefined;
33670 var rhs_buf: Value.ElemValueBuffer = undefined;
33671 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
33672 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
33673 scalar.* = try sema.intSubScalar(lhs_elem, rhs_elem);
34548 const lhs_elem = try lhs.elemValue(sema.mod, i);
34549 const rhs_elem = try rhs.elemValue(sema.mod, i);
34550 const val = sema.intSubScalar(lhs_elem, rhs_elem, scalar_ty) catch |err| switch (err) {
34551 error.Overflow => {
34552 overflow_idx.* = i;
34553 return error.Overflow;
34554 },
34555 else => |e| return e,
34556 };
34557 scalar.* = try val.intern(scalar_ty, mod);
3367434558 }
33675 return Value.Tag.aggregate.create(sema.arena, result_data);
34559 return (try mod.intern(.{ .aggregate = .{
34560 .ty = ty.toIntern(),
34561 .storage = .{ .elems = result_data },
34562 } })).toValue();
3367634563 }
33677 return sema.intSubScalar(lhs, rhs);
34564 return sema.intSubScalar(lhs, rhs, ty);
3367834565}
3367934566
33680fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value) !Value {
34567fn intSubScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
34568 const mod = sema.mod;
34569 if (scalar_ty.toIntern() != .comptime_int_type) {
34570 const res = try sema.intSubWithOverflowScalar(lhs, rhs, scalar_ty);
34571 if (res.overflow_bit.compareAllWithZero(.neq, mod)) return error.Overflow;
34572 return res.wrapped_result;
34573 }
3368134574 // TODO is this a performance issue? maybe we should try the operation without
3368234575 // resorting to BigInt first.
3368334576 var lhs_space: Value.BigIntSpace = undefined;
3368434577 var rhs_space: Value.BigIntSpace = undefined;
33685 const target = sema.mod.getTarget();
33686 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);
33687 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
34578 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
34579 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
3368834580 const limbs = try sema.arena.alloc(
3368934581 std.math.big.Limb,
3369034582 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len) + 1,
3369134583 );
3369234584 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3369334585 result_bigint.sub(lhs_bigint, rhs_bigint);
33694 return Value.fromBigInt(sema.arena, result_bigint.toConst());
34586 return mod.intValue_big(scalar_ty, result_bigint.toConst());
3369534587}
3369634588
3369734589/// Supports both floats and ints; handles undefined.
......@@ -33701,155 +34593,49 @@ fn numberSubWrapScalar(
3370134593 rhs: Value,
3370234594 ty: Type,
3370334595) !Value {
33704 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
34596 const mod = sema.mod;
34597 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;
3370534598
33706 if (ty.zigTypeTag() == .ComptimeInt) {
33707 return sema.intSub(lhs, rhs, ty);
34599 if (ty.zigTypeTag(mod) == .ComptimeInt) {
34600 return sema.intSub(lhs, rhs, ty, undefined);
3370834601 }
3370934602
3371034603 if (ty.isAnyFloat()) {
33711 return sema.floatSub(lhs, rhs, ty);
34604 return Value.floatSub(lhs, rhs, ty, sema.arena, mod);
3371234605 }
3371334606
3371434607 const overflow_result = try sema.intSubWithOverflow(lhs, rhs, ty);
3371534608 return overflow_result.wrapped_result;
3371634609}
3371734610
33718fn floatAdd(
33719 sema: *Sema,
33720 lhs: Value,
33721 rhs: Value,
33722 float_type: Type,
33723) !Value {
33724 if (float_type.zigTypeTag() == .Vector) {
33725 const result_data = try sema.arena.alloc(Value, float_type.vectorLen());
33726 for (result_data, 0..) |*scalar, i| {
33727 var lhs_buf: Value.ElemValueBuffer = undefined;
33728 var rhs_buf: Value.ElemValueBuffer = undefined;
33729 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
33730 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
33731 scalar.* = try sema.floatAddScalar(lhs_elem, rhs_elem, float_type.scalarType());
33732 }
33733 return Value.Tag.aggregate.create(sema.arena, result_data);
33734 }
33735 return sema.floatAddScalar(lhs, rhs, float_type);
33736}
33737
33738fn floatAddScalar(
33739 sema: *Sema,
33740 lhs: Value,
33741 rhs: Value,
33742 float_type: Type,
33743) !Value {
33744 const target = sema.mod.getTarget();
33745 switch (float_type.floatBits(target)) {
33746 16 => {
33747 const lhs_val = lhs.toFloat(f16);
33748 const rhs_val = rhs.toFloat(f16);
33749 return Value.Tag.float_16.create(sema.arena, lhs_val + rhs_val);
33750 },
33751 32 => {
33752 const lhs_val = lhs.toFloat(f32);
33753 const rhs_val = rhs.toFloat(f32);
33754 return Value.Tag.float_32.create(sema.arena, lhs_val + rhs_val);
33755 },
33756 64 => {
33757 const lhs_val = lhs.toFloat(f64);
33758 const rhs_val = rhs.toFloat(f64);
33759 return Value.Tag.float_64.create(sema.arena, lhs_val + rhs_val);
33760 },
33761 80 => {
33762 const lhs_val = lhs.toFloat(f80);
33763 const rhs_val = rhs.toFloat(f80);
33764 return Value.Tag.float_80.create(sema.arena, lhs_val + rhs_val);
33765 },
33766 128 => {
33767 const lhs_val = lhs.toFloat(f128);
33768 const rhs_val = rhs.toFloat(f128);
33769 return Value.Tag.float_128.create(sema.arena, lhs_val + rhs_val);
33770 },
33771 else => unreachable,
33772 }
33773}
33774
33775fn floatSub(
33776 sema: *Sema,
33777 lhs: Value,
33778 rhs: Value,
33779 float_type: Type,
33780) !Value {
33781 if (float_type.zigTypeTag() == .Vector) {
33782 const result_data = try sema.arena.alloc(Value, float_type.vectorLen());
33783 for (result_data, 0..) |*scalar, i| {
33784 var lhs_buf: Value.ElemValueBuffer = undefined;
33785 var rhs_buf: Value.ElemValueBuffer = undefined;
33786 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
33787 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
33788 scalar.* = try sema.floatSubScalar(lhs_elem, rhs_elem, float_type.scalarType());
33789 }
33790 return Value.Tag.aggregate.create(sema.arena, result_data);
33791 }
33792 return sema.floatSubScalar(lhs, rhs, float_type);
33793}
33794
33795fn floatSubScalar(
33796 sema: *Sema,
33797 lhs: Value,
33798 rhs: Value,
33799 float_type: Type,
33800) !Value {
33801 const target = sema.mod.getTarget();
33802 switch (float_type.floatBits(target)) {
33803 16 => {
33804 const lhs_val = lhs.toFloat(f16);
33805 const rhs_val = rhs.toFloat(f16);
33806 return Value.Tag.float_16.create(sema.arena, lhs_val - rhs_val);
33807 },
33808 32 => {
33809 const lhs_val = lhs.toFloat(f32);
33810 const rhs_val = rhs.toFloat(f32);
33811 return Value.Tag.float_32.create(sema.arena, lhs_val - rhs_val);
33812 },
33813 64 => {
33814 const lhs_val = lhs.toFloat(f64);
33815 const rhs_val = rhs.toFloat(f64);
33816 return Value.Tag.float_64.create(sema.arena, lhs_val - rhs_val);
33817 },
33818 80 => {
33819 const lhs_val = lhs.toFloat(f80);
33820 const rhs_val = rhs.toFloat(f80);
33821 return Value.Tag.float_80.create(sema.arena, lhs_val - rhs_val);
33822 },
33823 128 => {
33824 const lhs_val = lhs.toFloat(f128);
33825 const rhs_val = rhs.toFloat(f128);
33826 return Value.Tag.float_128.create(sema.arena, lhs_val - rhs_val);
33827 },
33828 else => unreachable,
33829 }
33830}
33831
3383234611fn intSubWithOverflow(
3383334612 sema: *Sema,
3383434613 lhs: Value,
3383534614 rhs: Value,
3383634615 ty: Type,
3383734616) !Value.OverflowArithmeticResult {
33838 if (ty.zigTypeTag() == .Vector) {
33839 const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen());
33840 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
33841 for (result_data, 0..) |*scalar, i| {
33842 var lhs_buf: Value.ElemValueBuffer = undefined;
33843 var rhs_buf: Value.ElemValueBuffer = undefined;
33844 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
33845 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
33846 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType());
33847 overflowed_data[i] = of_math_result.overflow_bit;
33848 scalar.* = of_math_result.wrapped_result;
34617 const mod = sema.mod;
34618 if (ty.zigTypeTag(mod) == .Vector) {
34619 const vec_len = ty.vectorLen(mod);
34620 const overflowed_data = try sema.arena.alloc(InternPool.Index, vec_len);
34621 const result_data = try sema.arena.alloc(InternPool.Index, vec_len);
34622 const scalar_ty = ty.scalarType(mod);
34623 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
34624 const lhs_elem = try lhs.elemValue(sema.mod, i);
34625 const rhs_elem = try rhs.elemValue(sema.mod, i);
34626 const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
34627 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
34628 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
3384934629 }
3385034630 return Value.OverflowArithmeticResult{
33851 .overflow_bit = try Value.Tag.aggregate.create(sema.arena, overflowed_data),
33852 .wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data),
34631 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34632 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
34633 .storage = .{ .elems = overflowed_data },
34634 } })).toValue(),
34635 .wrapped_result = (try mod.intern(.{ .aggregate = .{
34636 .ty = ty.toIntern(),
34637 .storage = .{ .elems = result_data },
34638 } })).toValue(),
3385334639 };
3385434640 }
3385534641 return sema.intSubWithOverflowScalar(lhs, rhs, ty);
......@@ -33861,22 +34647,22 @@ fn intSubWithOverflowScalar(
3386134647 rhs: Value,
3386234648 ty: Type,
3386334649) !Value.OverflowArithmeticResult {
33864 const target = sema.mod.getTarget();
33865 const info = ty.intInfo(target);
34650 const mod = sema.mod;
34651 const info = ty.intInfo(mod);
3386634652
3386734653 var lhs_space: Value.BigIntSpace = undefined;
3386834654 var rhs_space: Value.BigIntSpace = undefined;
33869 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);
33870 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
34655 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
34656 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
3387134657 const limbs = try sema.arena.alloc(
3387234658 std.math.big.Limb,
3387334659 std.math.big.int.calcTwosCompLimbCount(info.bits),
3387434660 );
3387534661 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3387634662 const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
33877 const wrapped_result = try Value.fromBigInt(sema.arena, result_bigint.toConst());
34663 const wrapped_result = try mod.intValue_big(ty, result_bigint.toConst());
3387834664 return Value.OverflowArithmeticResult{
33879 .overflow_bit = Value.boolToInt(overflowed),
34665 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3388034666 .wrapped_result = wrapped_result,
3388134667 };
3388234668}
......@@ -33889,15 +34675,19 @@ fn floatToInt(
3388934675 float_ty: Type,
3389034676 int_ty: Type,
3389134677) CompileError!Value {
33892 if (float_ty.zigTypeTag() == .Vector) {
33893 const elem_ty = float_ty.childType();
33894 const result_data = try sema.arena.alloc(Value, float_ty.vectorLen());
34678 const mod = sema.mod;
34679 if (float_ty.zigTypeTag(mod) == .Vector) {
34680 const elem_ty = float_ty.scalarType(mod);
34681 const result_data = try sema.arena.alloc(InternPool.Index, float_ty.vectorLen(mod));
34682 const scalar_ty = int_ty.scalarType(mod);
3389534683 for (result_data, 0..) |*scalar, i| {
33896 var buf: Value.ElemValueBuffer = undefined;
33897 const elem_val = val.elemValueBuffer(sema.mod, i, &buf);
33898 scalar.* = try sema.floatToIntScalar(block, src, elem_val, elem_ty, int_ty.scalarType());
34684 const elem_val = try val.elemValue(sema.mod, i);
34685 scalar.* = try (try sema.floatToIntScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod))).intern(scalar_ty, mod);
3389934686 }
33900 return Value.Tag.aggregate.create(sema.arena, result_data);
34687 return (try mod.intern(.{ .aggregate = .{
34688 .ty = int_ty.toIntern(),
34689 .storage = .{ .elems = result_data },
34690 } })).toValue();
3390134691 }
3390234692 return sema.floatToIntScalar(block, src, val, float_ty, int_ty);
3390334693}
......@@ -33935,9 +34725,9 @@ fn floatToIntScalar(
3393534725 float_ty: Type,
3393634726 int_ty: Type,
3393734727) CompileError!Value {
33938 const Limb = std.math.big.Limb;
34728 const mod = sema.mod;
3393934729
33940 const float = val.toFloat(f128);
34730 const float = val.toFloat(f128, mod);
3394134731 if (std.math.isNan(float)) {
3394234732 return sema.fail(block, src, "float value NaN cannot be stored in integer type '{}'", .{
3394334733 int_ty.fmt(sema.mod),
......@@ -33952,18 +34742,14 @@ fn floatToIntScalar(
3395234742 var big_int = try float128IntPartToBigInt(sema.arena, float);
3395334743 defer big_int.deinit();
3395434744
33955 const result_limbs = try sema.arena.dupe(Limb, big_int.toConst().limbs);
33956 const result = if (!big_int.isPositive())
33957 try Value.Tag.int_big_negative.create(sema.arena, result_limbs)
33958 else
33959 try Value.Tag.int_big_positive.create(sema.arena, result_limbs);
34745 const cti_result = try mod.intValue_big(Type.comptime_int, big_int.toConst());
3396034746
33961 if (!(try sema.intFitsInType(result, int_ty, null))) {
34747 if (!(try sema.intFitsInType(cti_result, int_ty, null))) {
3396234748 return sema.fail(block, src, "float value '{}' cannot be stored in integer type '{}'", .{
3396334749 val.fmtValue(float_ty, sema.mod), int_ty.fmt(sema.mod),
3396434750 });
3396534751 }
33966 return result;
34752 return mod.getCoerced(cti_result, int_ty);
3396734753}
3396834754
3396934755/// Asserts the value is an integer, and the destination type is ComptimeInt or Int.
......@@ -33976,208 +34762,91 @@ fn intFitsInType(
3397634762 ty: Type,
3397734763 vector_index: ?*usize,
3397834764) CompileError!bool {
33979 const target = sema.mod.getTarget();
33980 switch (val.tag()) {
33981 .zero,
33982 .undef,
33983 .bool_false,
33984 => return true,
33985
33986 .one,
33987 .bool_true,
33988 => switch (ty.zigTypeTag()) {
33989 .Int => {
33990 const info = ty.intInfo(target);
33991 return switch (info.signedness) {
33992 .signed => info.bits >= 2,
33993 .unsigned => info.bits >= 1,
33994 };
33995 },
33996 .ComptimeInt => return true,
33997 else => unreachable,
33998 },
33999
34000 .lazy_align => switch (ty.zigTypeTag()) {
34001 .Int => {
34002 const info = ty.intInfo(target);
34003 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34004 // If it is u16 or bigger we know the alignment fits without resolving it.
34005 if (info.bits >= max_needed_bits) return true;
34006 const x = try sema.typeAbiAlignment(val.castTag(.lazy_align).?.data);
34007 if (x == 0) return true;
34008 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34009 return info.bits >= actual_needed_bits;
34010 },
34011 .ComptimeInt => return true,
34012 else => unreachable,
34013 },
34014 .lazy_size => switch (ty.zigTypeTag()) {
34015 .Int => {
34016 const info = ty.intInfo(target);
34017 const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
34018 // If it is u64 or bigger we know the size fits without resolving it.
34019 if (info.bits >= max_needed_bits) return true;
34020 const x = try sema.typeAbiSize(val.castTag(.lazy_size).?.data);
34021 if (x == 0) return true;
34022 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34023 return info.bits >= actual_needed_bits;
34024 },
34025 .ComptimeInt => return true,
34026 else => unreachable,
34027 },
34028
34029 .int_u64 => switch (ty.zigTypeTag()) {
34030 .Int => {
34031 const x = val.castTag(.int_u64).?.data;
34032 if (x == 0) return true;
34033 const info = ty.intInfo(target);
34034 const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34035 return info.bits >= needed_bits;
34036 },
34037 .ComptimeInt => return true,
34038 else => unreachable,
34039 },
34040 .int_i64 => switch (ty.zigTypeTag()) {
34041 .Int => {
34042 const x = val.castTag(.int_i64).?.data;
34043 if (x == 0) return true;
34044 const info = ty.intInfo(target);
34045 if (info.signedness == .unsigned and x < 0)
34046 return false;
34047 var buffer: Value.BigIntSpace = undefined;
34048 return (try val.toBigIntAdvanced(&buffer, target, sema)).fitsInTwosComp(info.signedness, info.bits);
34049 },
34050 .ComptimeInt => return true,
34051 else => unreachable,
34052 },
34053 .int_big_positive => switch (ty.zigTypeTag()) {
34054 .Int => {
34055 const info = ty.intInfo(target);
34056 return val.castTag(.int_big_positive).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
34057 },
34058 .ComptimeInt => return true,
34059 else => unreachable,
34060 },
34061 .int_big_negative => switch (ty.zigTypeTag()) {
34062 .Int => {
34063 const info = ty.intInfo(target);
34064 return val.castTag(.int_big_negative).?.asBigInt().fitsInTwosComp(info.signedness, info.bits);
34065 },
34066 .ComptimeInt => return true,
34067 else => unreachable,
34068 },
34069
34070 .the_only_possible_value => {
34071 assert(ty.intInfo(target).bits == 0);
34072 return true;
34073 },
34074
34075 .decl_ref_mut,
34076 .extern_fn,
34077 .decl_ref,
34078 .function,
34079 .variable,
34080 => switch (ty.zigTypeTag()) {
34081 .Int => {
34082 const info = ty.intInfo(target);
34765 const mod = sema.mod;
34766 if (ty.toIntern() == .comptime_int_type) return true;
34767 const info = ty.intInfo(mod);
34768 switch (val.toIntern()) {
34769 .zero_usize, .zero_u8 => return true,
34770 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
34771 .undef => return true,
34772 .variable, .extern_func, .func, .ptr => {
34773 const target = mod.getTarget();
3408334774 const ptr_bits = target.ptrBitWidth();
3408434775 return switch (info.signedness) {
3408534776 .signed => info.bits > ptr_bits,
3408634777 .unsigned => info.bits >= ptr_bits,
3408734778 };
3408834779 },
34089 .ComptimeInt => return true,
34780 .int => |int| switch (int.storage) {
34781 .u64, .i64, .big_int => {
34782 var buffer: InternPool.Key.Int.Storage.BigIntSpace = undefined;
34783 const big_int = int.storage.toBigInt(&buffer);
34784 return big_int.fitsInTwosComp(info.signedness, info.bits);
34785 },
34786 .lazy_align => |lazy_ty| {
34787 const max_needed_bits = @as(u16, 16) + @boolToInt(info.signedness == .signed);
34788 // If it is u16 or bigger we know the alignment fits without resolving it.
34789 if (info.bits >= max_needed_bits) return true;
34790 const x = try sema.typeAbiAlignment(lazy_ty.toType());
34791 if (x == 0) return true;
34792 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34793 return info.bits >= actual_needed_bits;
34794 },
34795 .lazy_size => |lazy_ty| {
34796 const max_needed_bits = @as(u16, 64) + @boolToInt(info.signedness == .signed);
34797 // If it is u64 or bigger we know the size fits without resolving it.
34798 if (info.bits >= max_needed_bits) return true;
34799 const x = try sema.typeAbiSize(lazy_ty.toType());
34800 if (x == 0) return true;
34801 const actual_needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signedness == .signed);
34802 return info.bits >= actual_needed_bits;
34803 },
34804 },
34805 .aggregate => |aggregate| {
34806 assert(ty.zigTypeTag(mod) == .Vector);
34807 return switch (aggregate.storage) {
34808 .bytes => |bytes| for (bytes, 0..) |byte, i| {
34809 if (byte == 0) continue;
34810 const actual_needed_bits = std.math.log2(byte) + 1 + @boolToInt(info.signedness == .signed);
34811 if (info.bits >= actual_needed_bits) continue;
34812 if (vector_index) |vi| vi.* = i;
34813 break false;
34814 } else true,
34815 .elems, .repeated_elem => for (switch (aggregate.storage) {
34816 .bytes => unreachable,
34817 .elems => |elems| elems,
34818 .repeated_elem => |elem| @as(*const [1]InternPool.Index, &elem),
34819 }, 0..) |elem, i| {
34820 if (try sema.intFitsInType(elem.toValue(), ty.scalarType(mod), null)) continue;
34821 if (vector_index) |vi| vi.* = i;
34822 break false;
34823 } else true,
34824 };
34825 },
3409034826 else => unreachable,
3409134827 },
34092
34093 .aggregate => {
34094 assert(ty.zigTypeTag() == .Vector);
34095 for (val.castTag(.aggregate).?.data, 0..) |elem, i| {
34096 if (!(try sema.intFitsInType(elem, ty.scalarType(), null))) {
34097 if (vector_index) |some| some.* = i;
34098 return false;
34099 }
34100 }
34101 return true;
34102 },
34103
34104 else => unreachable,
3410534828 }
3410634829}
3410734830
34108fn intInRange(
34109 sema: *Sema,
34110 tag_ty: Type,
34111 int_val: Value,
34112 end: usize,
34113) !bool {
34831fn intInRange(sema: *Sema, tag_ty: Type, int_val: Value, end: usize) !bool {
34832 const mod = sema.mod;
3411434833 if (!(try int_val.compareAllWithZeroAdvanced(.gte, sema))) return false;
34115 var end_payload: Value.Payload.U64 = .{
34116 .base = .{ .tag = .int_u64 },
34117 .data = end,
34118 };
34119 const end_val = Value.initPayload(&end_payload.base);
34834 const end_val = try mod.intValue(tag_ty, end);
3412034835 if (!(try sema.compareAll(int_val, .lt, end_val, tag_ty))) return false;
3412134836 return true;
3412234837}
3412334838
3412434839/// Asserts the type is an enum.
34125fn enumHasInt(
34126 sema: *Sema,
34127 ty: Type,
34128 int: Value,
34129) CompileError!bool {
34130 switch (ty.tag()) {
34131 .enum_nonexhaustive => unreachable,
34132 .enum_full => {
34133 const enum_full = ty.castTag(.enum_full).?.data;
34134 const tag_ty = enum_full.tag_ty;
34135 if (enum_full.values.count() == 0) {
34136 return sema.intInRange(tag_ty, int, enum_full.fields.count());
34137 } else {
34138 return enum_full.values.containsContext(int, .{
34139 .ty = tag_ty,
34140 .mod = sema.mod,
34141 });
34142 }
34143 },
34144 .enum_numbered => {
34145 const enum_obj = ty.castTag(.enum_numbered).?.data;
34146 const tag_ty = enum_obj.tag_ty;
34147 if (enum_obj.values.count() == 0) {
34148 return sema.intInRange(tag_ty, int, enum_obj.fields.count());
34149 } else {
34150 return enum_obj.values.containsContext(int, .{
34151 .ty = tag_ty,
34152 .mod = sema.mod,
34153 });
34154 }
34155 },
34156 .enum_simple => {
34157 const enum_simple = ty.castTag(.enum_simple).?.data;
34158 const fields_len = enum_simple.fields.count();
34159 const bits = std.math.log2_int_ceil(usize, fields_len);
34160 var buffer: Type.Payload.Bits = .{
34161 .base = .{ .tag = .int_unsigned },
34162 .data = bits,
34163 };
34164 const tag_ty = Type.initPayload(&buffer.base);
34165 return sema.intInRange(tag_ty, int, fields_len);
34166 },
34167 .atomic_order,
34168 .atomic_rmw_op,
34169 .calling_convention,
34170 .address_space,
34171 .float_mode,
34172 .reduce_op,
34173 .modifier,
34174 .prefetch_options,
34175 .export_options,
34176 .extern_options,
34177 => unreachable,
34840fn enumHasInt(sema: *Sema, ty: Type, int: Value) CompileError!bool {
34841 const mod = sema.mod;
34842 const enum_type = mod.intern_pool.indexToKey(ty.toIntern()).enum_type;
34843 assert(enum_type.tag_mode != .nonexhaustive);
34844 // The `tagValueIndex` function call below relies on the type being the integer tag type.
34845 // `getCoerced` assumes the value will fit the new type.
34846 if (!(try sema.intFitsInType(int, enum_type.tag_ty.toType(), null))) return false;
34847 const int_coerced = try mod.getCoerced(int, enum_type.tag_ty.toType());
3417834848
34179 else => unreachable,
34180 }
34849 return enum_type.tagValueIndex(&mod.intern_pool, int_coerced.toIntern()) != null;
3418134850}
3418234851
3418334852fn intAddWithOverflow(
......@@ -34186,21 +34855,28 @@ fn intAddWithOverflow(
3418634855 rhs: Value,
3418734856 ty: Type,
3418834857) !Value.OverflowArithmeticResult {
34189 if (ty.zigTypeTag() == .Vector) {
34190 const overflowed_data = try sema.arena.alloc(Value, ty.vectorLen());
34191 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
34192 for (result_data, 0..) |*scalar, i| {
34193 var lhs_buf: Value.ElemValueBuffer = undefined;
34194 var rhs_buf: Value.ElemValueBuffer = undefined;
34195 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
34196 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
34197 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType());
34198 overflowed_data[i] = of_math_result.overflow_bit;
34199 scalar.* = of_math_result.wrapped_result;
34858 const mod = sema.mod;
34859 if (ty.zigTypeTag(mod) == .Vector) {
34860 const vec_len = ty.vectorLen(mod);
34861 const overflowed_data = try sema.arena.alloc(InternPool.Index, vec_len);
34862 const result_data = try sema.arena.alloc(InternPool.Index, vec_len);
34863 const scalar_ty = ty.scalarType(mod);
34864 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
34865 const lhs_elem = try lhs.elemValue(sema.mod, i);
34866 const rhs_elem = try rhs.elemValue(sema.mod, i);
34867 const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty);
34868 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
34869 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
3420034870 }
3420134871 return Value.OverflowArithmeticResult{
34202 .overflow_bit = try Value.Tag.aggregate.create(sema.arena, overflowed_data),
34203 .wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data),
34872 .overflow_bit = (try mod.intern(.{ .aggregate = .{
34873 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
34874 .storage = .{ .elems = overflowed_data },
34875 } })).toValue(),
34876 .wrapped_result = (try mod.intern(.{ .aggregate = .{
34877 .ty = ty.toIntern(),
34878 .storage = .{ .elems = result_data },
34879 } })).toValue(),
3420434880 };
3420534881 }
3420634882 return sema.intAddWithOverflowScalar(lhs, rhs, ty);
......@@ -34212,22 +34888,22 @@ fn intAddWithOverflowScalar(
3421234888 rhs: Value,
3421334889 ty: Type,
3421434890) !Value.OverflowArithmeticResult {
34215 const target = sema.mod.getTarget();
34216 const info = ty.intInfo(target);
34891 const mod = sema.mod;
34892 const info = ty.intInfo(mod);
3421734893
3421834894 var lhs_space: Value.BigIntSpace = undefined;
3421934895 var rhs_space: Value.BigIntSpace = undefined;
34220 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, target, sema);
34221 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, target, sema);
34896 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_space, mod, sema);
34897 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_space, mod, sema);
3422234898 const limbs = try sema.arena.alloc(
3422334899 std.math.big.Limb,
3422434900 std.math.big.int.calcTwosCompLimbCount(info.bits),
3422534901 );
3422634902 var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
3422734903 const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
34228 const result = try Value.fromBigInt(sema.arena, result_bigint.toConst());
34904 const result = try mod.intValue_big(ty, result_bigint.toConst());
3422934905 return Value.OverflowArithmeticResult{
34230 .overflow_bit = Value.boolToInt(overflowed),
34906 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3423134907 .wrapped_result = result,
3423234908 };
3423334909}
......@@ -34243,14 +34919,13 @@ fn compareAll(
3424334919 rhs: Value,
3424434920 ty: Type,
3424534921) CompileError!bool {
34246 if (ty.zigTypeTag() == .Vector) {
34922 const mod = sema.mod;
34923 if (ty.zigTypeTag(mod) == .Vector) {
3424734924 var i: usize = 0;
34248 while (i < ty.vectorLen()) : (i += 1) {
34249 var lhs_buf: Value.ElemValueBuffer = undefined;
34250 var rhs_buf: Value.ElemValueBuffer = undefined;
34251 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
34252 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
34253 if (!(try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType()))) {
34925 while (i < ty.vectorLen(mod)) : (i += 1) {
34926 const lhs_elem = try lhs.elemValue(sema.mod, i);
34927 const rhs_elem = try rhs.elemValue(sema.mod, i);
34928 if (!(try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod)))) {
3425434929 return false;
3425534930 }
3425634931 }
......@@ -34267,10 +34942,13 @@ fn compareScalar(
3426734942 rhs: Value,
3426834943 ty: Type,
3426934944) CompileError!bool {
34945 const mod = sema.mod;
34946 const coerced_lhs = try mod.getCoerced(lhs, ty);
34947 const coerced_rhs = try mod.getCoerced(rhs, ty);
3427034948 switch (op) {
34271 .eq => return sema.valuesEqual(lhs, rhs, ty),
34272 .neq => return !(try sema.valuesEqual(lhs, rhs, ty)),
34273 else => return Value.compareHeteroAdvanced(lhs, op, rhs, sema.mod.getTarget(), sema),
34949 .eq => return sema.valuesEqual(coerced_lhs, coerced_rhs, ty),
34950 .neq => return !(try sema.valuesEqual(coerced_lhs, coerced_rhs, ty)),
34951 else => return Value.compareHeteroAdvanced(coerced_lhs, op, coerced_rhs, mod, sema),
3427434952 }
3427534953}
3427634954
......@@ -34291,17 +34969,19 @@ fn compareVector(
3429134969 rhs: Value,
3429234970 ty: Type,
3429334971) !Value {
34294 assert(ty.zigTypeTag() == .Vector);
34295 const result_data = try sema.arena.alloc(Value, ty.vectorLen());
34972 const mod = sema.mod;
34973 assert(ty.zigTypeTag(mod) == .Vector);
34974 const result_data = try sema.arena.alloc(InternPool.Index, ty.vectorLen(mod));
3429634975 for (result_data, 0..) |*scalar, i| {
34297 var lhs_buf: Value.ElemValueBuffer = undefined;
34298 var rhs_buf: Value.ElemValueBuffer = undefined;
34299 const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
34300 const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
34301 const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType());
34302 scalar.* = Value.makeBool(res_bool);
34976 const lhs_elem = try lhs.elemValue(sema.mod, i);
34977 const rhs_elem = try rhs.elemValue(sema.mod, i);
34978 const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod));
34979 scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod);
3430334980 }
34304 return Value.Tag.aggregate.create(sema.arena, result_data);
34981 return (try mod.intern(.{ .aggregate = .{
34982 .ty = (try mod.vectorType(.{ .len = ty.vectorLen(mod), .child = .bool_type })).toIntern(),
34983 .storage = .{ .elems = result_data },
34984 } })).toValue();
3430534985}
3430634986
3430734987/// Returns the type of a pointer to an element.
......@@ -34312,11 +34992,11 @@ fn compareVector(
3431234992/// Handles const-ness and address spaces in particular.
3431334993/// This code is duplicated in `analyzePtrArithmetic`.
3431434994fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
34315 const ptr_info = ptr_ty.ptrInfo().data;
34316 const elem_ty = ptr_ty.elemType2();
34995 const mod = sema.mod;
34996 const ptr_info = ptr_ty.ptrInfo(mod);
34997 const elem_ty = ptr_ty.elemType2(mod);
3431734998 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;
34318 const target = sema.mod.getTarget();
34319 const parent_ty = ptr_ty.childType();
34999 const parent_ty = ptr_ty.childType(mod);
3432035000
3432135001 const VI = Type.Payload.Pointer.Data.VectorIndex;
3432235002
......@@ -34324,15 +35004,15 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
3432435004 host_size: u16 = 0,
3432535005 alignment: u32 = 0,
3432635006 vector_index: VI = .none,
34327 } = if (parent_ty.tag() == .vector and ptr_info.size == .One) blk: {
34328 const elem_bits = elem_ty.bitSize(target);
35007 } = if (parent_ty.isVector(mod) and ptr_info.size == .One) blk: {
35008 const elem_bits = elem_ty.bitSize(mod);
3432935009 if (elem_bits == 0) break :blk .{};
3433035010 const is_packed = elem_bits < 8 or !std.math.isPowerOfTwo(elem_bits);
3433135011 if (!is_packed) break :blk .{};
3433235012
3433335013 break :blk .{
34334 .host_size = @intCast(u16, parent_ty.arrayLen()),
34335 .alignment = @intCast(u16, parent_ty.abiAlignment(target)),
35014 .host_size = @intCast(u16, parent_ty.arrayLen(mod)),
35015 .alignment = @intCast(u16, parent_ty.abiAlignment(mod)),
3433635016 .vector_index = if (offset) |some| @intToEnum(VI, some) else .runtime,
3433735017 };
3433835018 } else .{};
......@@ -34366,3 +35046,42 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
3436635046 .vector_index = vector_info.vector_index,
3436735047 });
3436835048}
35049
35050/// Merge lhs with rhs.
35051/// Asserts that lhs and rhs are both error sets and are resolved.
35052fn errorSetMerge(sema: *Sema, lhs: Type, rhs: Type) !Type {
35053 const mod = sema.mod;
35054 const arena = sema.arena;
35055 const lhs_names = lhs.errorSetNames(mod);
35056 const rhs_names = rhs.errorSetNames(mod);
35057 var names: Module.Fn.InferredErrorSet.NameMap = .{};
35058 try names.ensureUnusedCapacity(arena, lhs_names.len);
35059
35060 for (lhs_names) |name| {
35061 names.putAssumeCapacityNoClobber(name, {});
35062 }
35063 for (rhs_names) |name| {
35064 try names.put(arena, name, {});
35065 }
35066
35067 return mod.errorSetFromUnsortedNames(names.keys());
35068}
35069
35070/// Avoids crashing the compiler when asking if inferred allocations are noreturn.
35071fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool {
35072 if (ref == .unreachable_value) return true;
35073 if (Air.refToIndex(ref)) |inst| switch (sema.air_instructions.items(.tag)[inst]) {
35074 .inferred_alloc, .inferred_alloc_comptime => return false,
35075 else => {},
35076 };
35077 return sema.typeOf(ref).isNoReturn(sema.mod);
35078}
35079
35080/// Avoids crashing the compiler when asking if inferred allocations are known to be a certain zig type.
35081fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool {
35082 if (Air.refToIndex(ref)) |inst| switch (sema.air_instructions.items(.tag)[inst]) {
35083 .inferred_alloc, .inferred_alloc_comptime => return false,
35084 else => {},
35085 };
35086 return sema.typeOf(ref).zigTypeTag(sema.mod) == tag;
35087}
src/TypedValue.zig+358-378
......@@ -27,13 +27,13 @@ pub const Managed = struct {
2727/// Assumes arena allocation. Does a recursive copy.
2828pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue {
2929 return TypedValue{
30 .ty = try self.ty.copy(arena),
30 .ty = self.ty,
3131 .val = try self.val.copy(arena),
3232 };
3333}
3434
3535pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool {
36 if (!a.ty.eql(b.ty, mod)) return false;
36 if (a.ty.toIntern() != b.ty.toIntern()) return false;
3737 return a.val.eql(b.val, a.ty, mod);
3838}
3939
......@@ -41,8 +41,8 @@ pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void {
4141 return tv.val.hash(tv.ty, hasher, mod);
4242}
4343
44pub fn enumToInt(tv: TypedValue, buffer: *Value.Payload.U64) Value {
45 return tv.val.enumToInt(tv.ty, buffer);
44pub fn enumToInt(tv: TypedValue, mod: *Module) Allocator.Error!Value {
45 return tv.val.enumToInt(tv.ty, mod);
4646}
4747
4848const max_aggregate_items = 100;
......@@ -61,7 +61,10 @@ pub fn format(
6161) !void {
6262 _ = options;
6363 comptime std.debug.assert(fmt.len == 0);
64 return ctx.tv.print(writer, 3, ctx.mod);
64 return ctx.tv.print(writer, 3, ctx.mod) catch |err| switch (err) {
65 error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
66 else => |e| return e,
67 };
6568}
6669
6770/// Prints the Value according to the Type, not according to the Value Tag.
......@@ -70,106 +73,61 @@ pub fn print(
7073 writer: anytype,
7174 level: u8,
7275 mod: *Module,
73) @TypeOf(writer).Error!void {
74 const target = mod.getTarget();
76) (@TypeOf(writer).Error || Allocator.Error)!void {
7577 var val = tv.val;
7678 var ty = tv.ty;
77 if (val.isVariable(mod))
78 return writer.writeAll("(variable)");
79
80 while (true) switch (val.tag()) {
81 .u1_type => return writer.writeAll("u1"),
82 .u8_type => return writer.writeAll("u8"),
83 .i8_type => return writer.writeAll("i8"),
84 .u16_type => return writer.writeAll("u16"),
85 .i16_type => return writer.writeAll("i16"),
86 .u29_type => return writer.writeAll("u29"),
87 .u32_type => return writer.writeAll("u32"),
88 .i32_type => return writer.writeAll("i32"),
89 .u64_type => return writer.writeAll("u64"),
90 .i64_type => return writer.writeAll("i64"),
91 .u128_type => return writer.writeAll("u128"),
92 .i128_type => return writer.writeAll("i128"),
93 .isize_type => return writer.writeAll("isize"),
94 .usize_type => return writer.writeAll("usize"),
95 .c_char_type => return writer.writeAll("c_char"),
96 .c_short_type => return writer.writeAll("c_short"),
97 .c_ushort_type => return writer.writeAll("c_ushort"),
98 .c_int_type => return writer.writeAll("c_int"),
99 .c_uint_type => return writer.writeAll("c_uint"),
100 .c_long_type => return writer.writeAll("c_long"),
101 .c_ulong_type => return writer.writeAll("c_ulong"),
102 .c_longlong_type => return writer.writeAll("c_longlong"),
103 .c_ulonglong_type => return writer.writeAll("c_ulonglong"),
104 .c_longdouble_type => return writer.writeAll("c_longdouble"),
105 .f16_type => return writer.writeAll("f16"),
106 .f32_type => return writer.writeAll("f32"),
107 .f64_type => return writer.writeAll("f64"),
108 .f80_type => return writer.writeAll("f80"),
109 .f128_type => return writer.writeAll("f128"),
110 .anyopaque_type => return writer.writeAll("anyopaque"),
111 .bool_type => return writer.writeAll("bool"),
112 .void_type => return writer.writeAll("void"),
113 .type_type => return writer.writeAll("type"),
114 .anyerror_type => return writer.writeAll("anyerror"),
115 .comptime_int_type => return writer.writeAll("comptime_int"),
116 .comptime_float_type => return writer.writeAll("comptime_float"),
117 .noreturn_type => return writer.writeAll("noreturn"),
118 .null_type => return writer.writeAll("@Type(.Null)"),
119 .undefined_type => return writer.writeAll("@Type(.Undefined)"),
120 .fn_noreturn_no_args_type => return writer.writeAll("fn() noreturn"),
121 .fn_void_no_args_type => return writer.writeAll("fn() void"),
122 .fn_naked_noreturn_no_args_type => return writer.writeAll("fn() callconv(.Naked) noreturn"),
123 .fn_ccc_void_no_args_type => return writer.writeAll("fn() callconv(.C) void"),
124 .single_const_pointer_to_comptime_int_type => return writer.writeAll("*const comptime_int"),
125 .anyframe_type => return writer.writeAll("anyframe"),
126 .const_slice_u8_type => return writer.writeAll("[]const u8"),
127 .const_slice_u8_sentinel_0_type => return writer.writeAll("[:0]const u8"),
128 .anyerror_void_error_union_type => return writer.writeAll("anyerror!void"),
129
130 .enum_literal_type => return writer.writeAll("@Type(.EnumLiteral)"),
131 .manyptr_u8_type => return writer.writeAll("[*]u8"),
132 .manyptr_const_u8_type => return writer.writeAll("[*]const u8"),
133 .manyptr_const_u8_sentinel_0_type => return writer.writeAll("[*:0]const u8"),
134 .atomic_order_type => return writer.writeAll("std.builtin.AtomicOrder"),
135 .atomic_rmw_op_type => return writer.writeAll("std.builtin.AtomicRmwOp"),
136 .calling_convention_type => return writer.writeAll("std.builtin.CallingConvention"),
137 .address_space_type => return writer.writeAll("std.builtin.AddressSpace"),
138 .float_mode_type => return writer.writeAll("std.builtin.FloatMode"),
139 .reduce_op_type => return writer.writeAll("std.builtin.ReduceOp"),
140 .modifier_type => return writer.writeAll("std.builtin.CallModifier"),
141 .prefetch_options_type => return writer.writeAll("std.builtin.PrefetchOptions"),
142 .export_options_type => return writer.writeAll("std.builtin.ExportOptions"),
143 .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"),
144 .type_info_type => return writer.writeAll("std.builtin.Type"),
79 const ip = &mod.intern_pool;
80 while (true) switch (val.ip_index) {
81 .none => switch (val.tag()) {
82 .aggregate => return printAggregate(ty, val, writer, level, mod),
83 .@"union" => {
84 if (level == 0) {
85 return writer.writeAll(".{ ... }");
86 }
87 const union_val = val.castTag(.@"union").?.data;
88 try writer.writeAll(".{ ");
14589
146 .empty_struct_value, .aggregate => {
147 if (level == 0) {
148 return writer.writeAll(".{ ... }");
149 }
150 if (ty.zigTypeTag() == .Struct) {
151 try writer.writeAll(".{");
152 const max_len = std.math.min(ty.structFieldCount(), max_aggregate_items);
90 try print(.{
91 .ty = mod.unionPtr(ip.indexToKey(ty.toIntern()).union_type.index).tag_ty,
92 .val = union_val.tag,
93 }, writer, level - 1, mod);
94 try writer.writeAll(" = ");
95 try print(.{
96 .ty = ty.unionFieldType(union_val.tag, mod),
97 .val = union_val.val,
98 }, writer, level - 1, mod);
15399
100 return writer.writeAll(" }");
101 },
102 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
103 .repeated => {
104 if (level == 0) {
105 return writer.writeAll(".{ ... }");
106 }
154107 var i: u32 = 0;
108 try writer.writeAll(".{ ");
109 const elem_tv = TypedValue{
110 .ty = ty.elemType2(mod),
111 .val = val.castTag(.repeated).?.data,
112 };
113 const len = ty.arrayLen(mod);
114 const max_len = std.math.min(len, max_aggregate_items);
155115 while (i < max_len) : (i += 1) {
156116 if (i != 0) try writer.writeAll(", ");
157 switch (ty.tag()) {
158 .anon_struct, .@"struct" => try writer.print(".{s} = ", .{ty.structFieldName(i)}),
159 else => {},
160 }
161 try print(.{
162 .ty = ty.structFieldType(i),
163 .val = val.fieldValue(ty, i),
164 }, writer, level - 1, mod);
117 try print(elem_tv, writer, level - 1, mod);
165118 }
166 if (ty.structFieldCount() > max_aggregate_items) {
119 if (len > max_aggregate_items) {
167120 try writer.writeAll(", ...");
168121 }
169 return writer.writeAll("}");
170 } else {
171 const elem_ty = ty.elemType2();
172 const len = ty.arrayLen();
122 return writer.writeAll(" }");
123 },
124 .slice => {
125 if (level == 0) {
126 return writer.writeAll(".{ ... }");
127 }
128 const payload = val.castTag(.slice).?.data;
129 const elem_ty = ty.elemType2(mod);
130 const len = payload.len.toUnsignedInt(mod);
173131
174132 if (elem_ty.eql(Type.u8, mod)) str: {
175133 const max_len = @intCast(usize, std.math.min(len, max_string_len));
......@@ -177,11 +135,14 @@ pub fn print(
177135
178136 var i: u32 = 0;
179137 while (i < max_len) : (i += 1) {
180 const elem = val.fieldValue(ty, i);
181 if (elem.isUndef()) break :str;
182 buf[i] = std.math.cast(u8, elem.toUnsignedInt(target)) orelse break :str;
138 const elem_val = payload.ptr.elemValue(mod, i) catch |err| switch (err) {
139 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
140 };
141 if (elem_val.isUndef(mod)) break :str;
142 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str;
183143 }
184144
145 // TODO would be nice if this had a bit of unicode awareness.
185146 const truncated = if (len > max_string_len) " (truncated)" else "";
186147 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
187148 }
......@@ -192,315 +153,334 @@ pub fn print(
192153 var i: u32 = 0;
193154 while (i < max_len) : (i += 1) {
194155 if (i != 0) try writer.writeAll(", ");
156 const elem_val = payload.ptr.elemValue(mod, i) catch |err| switch (err) {
157 error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic
158 };
195159 try print(.{
196160 .ty = elem_ty,
197 .val = val.fieldValue(ty, i),
161 .val = elem_val,
198162 }, writer, level - 1, mod);
199163 }
200164 if (len > max_aggregate_items) {
201165 try writer.writeAll(", ...");
202166 }
203167 return writer.writeAll(" }");
204 }
205 },
206 .@"union" => {
207 if (level == 0) {
208 return writer.writeAll(".{ ... }");
209 }
210 const union_val = val.castTag(.@"union").?.data;
211 try writer.writeAll(".{ ");
212
213 try print(.{
214 .ty = ty.cast(Type.Payload.Union).?.data.tag_ty,
215 .val = union_val.tag,
216 }, writer, level - 1, mod);
217 try writer.writeAll(" = ");
218 try print(.{
219 .ty = ty.unionFieldType(union_val.tag, mod),
220 .val = union_val.val,
221 }, writer, level - 1, mod);
222
223 return writer.writeAll(" }");
224 },
225 .null_value => return writer.writeAll("null"),
226 .undef => return writer.writeAll("undefined"),
227 .zero => return writer.writeAll("0"),
228 .one => return writer.writeAll("1"),
229 .void_value => return writer.writeAll("{}"),
230 .unreachable_value => return writer.writeAll("unreachable"),
231 .the_only_possible_value => return writer.writeAll("0"),
232 .bool_true => return writer.writeAll("true"),
233 .bool_false => return writer.writeAll("false"),
234 .ty => return val.castTag(.ty).?.data.print(writer, mod),
235 .int_type => {
236 const int_type = val.castTag(.int_type).?.data;
237 return writer.print("{s}{d}", .{
238 if (int_type.signed) "s" else "u",
239 int_type.bits,
240 });
241 },
242 .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer),
243 .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer),
244 .int_big_positive => return writer.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}),
245 .int_big_negative => return writer.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}),
246 .lazy_align => {
247 const sub_ty = val.castTag(.lazy_align).?.data;
248 const x = sub_ty.abiAlignment(target);
249 return writer.print("{d}", .{x});
168 },
169 .eu_payload => {
170 val = val.castTag(.eu_payload).?.data;
171 ty = ty.errorUnionPayload(mod);
172 },
173 .opt_payload => {
174 val = val.castTag(.opt_payload).?.data;
175 ty = ty.optionalChild(mod);
176 },
250177 },
251 .lazy_size => {
252 const sub_ty = val.castTag(.lazy_size).?.data;
253 const x = sub_ty.abiSize(target);
254 return writer.print("{d}", .{x});
255 },
256 .function => return writer.print("(function '{s}')", .{
257 mod.declPtr(val.castTag(.function).?.data.owner_decl).name,
258 }),
259 .extern_fn => return writer.writeAll("(extern function)"),
260 .variable => unreachable,
261 .decl_ref_mut => {
262 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
263 const decl = mod.declPtr(decl_index);
264 if (level == 0) {
265 return writer.print("(decl ref mut '{s}')", .{decl.name});
266 }
267 return print(.{
268 .ty = decl.ty,
269 .val = decl.val,
270 }, writer, level - 1, mod);
271 },
272 .decl_ref => {
273 const decl_index = val.castTag(.decl_ref).?.data;
274 const decl = mod.declPtr(decl_index);
275 if (level == 0) {
276 return writer.print("(decl ref '{s}')", .{decl.name});
277 }
278 return print(.{
279 .ty = decl.ty,
280 .val = decl.val,
281 }, writer, level - 1, mod);
282 },
283 .comptime_field_ptr => {
284 const payload = val.castTag(.comptime_field_ptr).?.data;
285 if (level == 0) {
286 return writer.writeAll("(comptime field ptr)");
287 }
288 return print(.{
289 .ty = payload.field_ty,
290 .val = payload.field_val,
291 }, writer, level - 1, mod);
292 },
293 .elem_ptr => {
294 const elem_ptr = val.castTag(.elem_ptr).?.data;
295 try writer.writeAll("&");
296 if (level == 0) {
297 try writer.writeAll("(ptr)");
298 } else {
178 else => switch (ip.indexToKey(val.toIntern())) {
179 .int_type,
180 .ptr_type,
181 .array_type,
182 .vector_type,
183 .opt_type,
184 .anyframe_type,
185 .error_union_type,
186 .simple_type,
187 .struct_type,
188 .anon_struct_type,
189 .union_type,
190 .opaque_type,
191 .enum_type,
192 .func_type,
193 .error_set_type,
194 .inferred_error_set_type,
195 => return Type.print(val.toType(), writer, mod),
196 .undef => return writer.writeAll("undefined"),
197 .runtime_value => return writer.writeAll("(runtime value)"),
198 .simple_value => |simple_value| switch (simple_value) {
199 .empty_struct => return printAggregate(ty, val, writer, level, mod),
200 .generic_poison => return writer.writeAll("(generic poison)"),
201 else => return writer.writeAll(@tagName(simple_value)),
202 },
203 .variable => return writer.writeAll("(variable)"),
204 .extern_func => |extern_func| return writer.print("(extern function '{}')", .{
205 mod.declPtr(extern_func.decl).name.fmt(ip),
206 }),
207 .func => |func| return writer.print("(function '{}')", .{
208 mod.declPtr(mod.funcPtr(func.index).owner_decl).name.fmt(ip),
209 }),
210 .int => |int| switch (int.storage) {
211 inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}),
212 .lazy_align => |lazy_ty| return writer.print("{d}", .{
213 lazy_ty.toType().abiAlignment(mod),
214 }),
215 .lazy_size => |lazy_ty| return writer.print("{d}", .{
216 lazy_ty.toType().abiSize(mod),
217 }),
218 },
219 .err => |err| return writer.print("error.{}", .{
220 err.name.fmt(ip),
221 }),
222 .error_union => |error_union| switch (error_union.val) {
223 .err_name => |err_name| return writer.print("error.{}", .{
224 err_name.fmt(ip),
225 }),
226 .payload => |payload| {
227 val = payload.toValue();
228 ty = ty.errorUnionPayload(mod);
229 },
230 },
231 .enum_literal => |enum_literal| return writer.print(".{}", .{
232 enum_literal.fmt(ip),
233 }),
234 .enum_tag => |enum_tag| {
235 if (level == 0) {
236 return writer.writeAll("(enum)");
237 }
238 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
239 if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| {
240 try writer.print(".{i}", .{enum_type.names[tag_index].fmt(ip)});
241 return;
242 }
243 try writer.writeAll("@intToEnum(");
299244 try print(.{
300 .ty = elem_ptr.elem_ty,
301 .val = elem_ptr.array_ptr,
245 .ty = Type.type,
246 .val = enum_tag.ty.toValue(),
302247 }, writer, level - 1, mod);
303 }
304 return writer.print("[{}]", .{elem_ptr.index});
305 },
306 .field_ptr => {
307 const field_ptr = val.castTag(.field_ptr).?.data;
308 try writer.writeAll("&");
309 if (level == 0) {
310 try writer.writeAll("(ptr)");
311 } else {
248 try writer.writeAll(", ");
312249 try print(.{
313 .ty = field_ptr.container_ty,
314 .val = field_ptr.container_ptr,
250 .ty = ip.typeOf(enum_tag.int).toType(),
251 .val = enum_tag.int.toValue(),
315252 }, writer, level - 1, mod);
316 }
317
318 if (field_ptr.container_ty.zigTypeTag() == .Struct) {
319 switch (field_ptr.container_ty.tag()) {
320 .tuple => return writer.print(".@\"{d}\"", .{field_ptr.field_index}),
321 else => {
322 const field_name = field_ptr.container_ty.structFieldName(field_ptr.field_index);
323 return writer.print(".{s}", .{field_name});
324 },
325 }
326 } else if (field_ptr.container_ty.zigTypeTag() == .Union) {
327 const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index];
328 return writer.print(".{s}", .{field_name});
329 } else if (field_ptr.container_ty.isSlice()) {
330 switch (field_ptr.field_index) {
331 Value.Payload.Slice.ptr_index => return writer.writeAll(".ptr"),
332 Value.Payload.Slice.len_index => return writer.writeAll(".len"),
333 else => unreachable,
253 try writer.writeAll(")");
254 return;
255 },
256 .empty_enum_value => return writer.writeAll("(empty enum value)"),
257 .float => |float| switch (float.storage) {
258 inline else => |x| return writer.print("{d}", .{@floatCast(f64, x)}),
259 },
260 .ptr => |ptr| {
261 if (ptr.addr == .int) {
262 const i = ip.indexToKey(ptr.addr.int).int;
263 switch (i.storage) {
264 inline else => |addr| return writer.print("{x:0>8}", .{addr}),
265 }
334266 }
335 }
336 },
337 .empty_array => return writer.writeAll(".{}"),
338 .enum_literal => return writer.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}),
339 .enum_field_index => {
340 return writer.print(".{s}", .{ty.enumFieldName(val.castTag(.enum_field_index).?.data)});
341 },
342 .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
343 .str_lit => {
344 const str_lit = val.castTag(.str_lit).?.data;
345 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
346 return writer.print("\"{}\"", .{std.zig.fmtEscapes(bytes)});
347 },
348 .repeated => {
349 if (level == 0) {
350 return writer.writeAll(".{ ... }");
351 }
352 var i: u32 = 0;
353 try writer.writeAll(".{ ");
354 const elem_tv = TypedValue{
355 .ty = ty.elemType2(),
356 .val = val.castTag(.repeated).?.data,
357 };
358 const len = ty.arrayLen();
359 const max_len = std.math.min(len, max_aggregate_items);
360 while (i < max_len) : (i += 1) {
361 if (i != 0) try writer.writeAll(", ");
362 try print(elem_tv, writer, level - 1, mod);
363 }
364 if (len > max_aggregate_items) {
365 try writer.writeAll(", ...");
366 }
367 return writer.writeAll(" }");
368 },
369 .empty_array_sentinel => {
370 if (level == 0) {
371 return writer.writeAll(".{ (sentinel) }");
372 }
373 try writer.writeAll(".{ ");
374 try print(.{
375 .ty = ty.elemType2(),
376 .val = ty.sentinel().?,
377 }, writer, level - 1, mod);
378 return writer.writeAll(" }");
379 },
380 .slice => {
381 if (level == 0) {
382 return writer.writeAll(".{ ... }");
383 }
384 const payload = val.castTag(.slice).?.data;
385 const elem_ty = ty.elemType2();
386 const len = payload.len.toUnsignedInt(target);
387267
388 if (elem_ty.eql(Type.u8, mod)) str: {
389 const max_len = @intCast(usize, std.math.min(len, max_string_len));
390 var buf: [max_string_len]u8 = undefined;
391
392 var i: u32 = 0;
393 while (i < max_len) : (i += 1) {
394 var elem_buf: Value.ElemValueBuffer = undefined;
395 const elem_val = payload.ptr.elemValueBuffer(mod, i, &elem_buf);
396 if (elem_val.isUndef()) break :str;
397 buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(target)) orelse break :str;
268 const ptr_ty = ip.indexToKey(ty.toIntern()).ptr_type;
269 if (ptr_ty.flags.size == .Slice) {
270 if (level == 0) {
271 return writer.writeAll(".{ ... }");
272 }
273 const elem_ty = ptr_ty.child.toType();
274 const len = ptr.len.toValue().toUnsignedInt(mod);
275 if (elem_ty.eql(Type.u8, mod)) str: {
276 const max_len = @min(len, max_string_len);
277 var buf: [max_string_len]u8 = undefined;
278 for (buf[0..max_len], 0..) |*c, i| {
279 const elem = try val.elemValue(mod, i);
280 if (elem.isUndef(mod)) break :str;
281 c.* = @intCast(u8, elem.toUnsignedInt(mod));
282 }
283 const truncated = if (len > max_string_len) " (truncated)" else "";
284 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
285 }
286 try writer.writeAll(".{ ");
287 const max_len = @min(len, max_aggregate_items);
288 for (0..max_len) |i| {
289 if (i != 0) try writer.writeAll(", ");
290 try print(.{
291 .ty = elem_ty,
292 .val = try val.elemValue(mod, i),
293 }, writer, level - 1, mod);
294 }
295 if (len > max_aggregate_items) {
296 try writer.writeAll(", ...");
297 }
298 return writer.writeAll(" }");
398299 }
399300
400 // TODO would be nice if this had a bit of unicode awareness.
401 const truncated = if (len > max_string_len) " (truncated)" else "";
402 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
403 }
404
405 try writer.writeAll(".{ ");
406
407 const max_len = std.math.min(len, max_aggregate_items);
408 var i: u32 = 0;
409 while (i < max_len) : (i += 1) {
410 if (i != 0) try writer.writeAll(", ");
411 var buf: Value.ElemValueBuffer = undefined;
412 try print(.{
413 .ty = elem_ty,
414 .val = payload.ptr.elemValueBuffer(mod, i, &buf),
415 }, writer, level - 1, mod);
416 }
417 if (len > max_aggregate_items) {
418 try writer.writeAll(", ...");
419 }
420 return writer.writeAll(" }");
421 },
422 .float_16 => return writer.print("{d}", .{val.castTag(.float_16).?.data}),
423 .float_32 => return writer.print("{d}", .{val.castTag(.float_32).?.data}),
424 .float_64 => return writer.print("{d}", .{val.castTag(.float_64).?.data}),
425 .float_80 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_80).?.data)}),
426 .float_128 => return writer.print("{d}", .{@floatCast(f64, val.castTag(.float_128).?.data)}),
427 .@"error" => return writer.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
428 .eu_payload => {
429 val = val.castTag(.eu_payload).?.data;
430 ty = ty.errorUnionPayload();
431 },
432 .opt_payload => {
433 val = val.castTag(.opt_payload).?.data;
434 var buf: Type.Payload.ElemType = undefined;
435 ty = ty.optionalChild(&buf);
436 return print(.{ .ty = ty, .val = val }, writer, level, mod);
301 switch (ptr.addr) {
302 .decl => |decl_index| {
303 const decl = mod.declPtr(decl_index);
304 if (level == 0) return writer.print("(decl '{}')", .{decl.name.fmt(ip)});
305 return print(.{
306 .ty = decl.ty,
307 .val = decl.val,
308 }, writer, level - 1, mod);
309 },
310 .mut_decl => |mut_decl| {
311 const decl = mod.declPtr(mut_decl.decl);
312 if (level == 0) return writer.print("(mut decl '{}')", .{decl.name.fmt(ip)});
313 return print(.{
314 .ty = decl.ty,
315 .val = decl.val,
316 }, writer, level - 1, mod);
317 },
318 .comptime_field => |field_val_ip| {
319 return print(.{
320 .ty = ip.typeOf(field_val_ip).toType(),
321 .val = field_val_ip.toValue(),
322 }, writer, level - 1, mod);
323 },
324 .int => unreachable,
325 .eu_payload => |eu_ip| {
326 try writer.writeAll("(payload of ");
327 try print(.{
328 .ty = ip.typeOf(eu_ip).toType(),
329 .val = eu_ip.toValue(),
330 }, writer, level - 1, mod);
331 try writer.writeAll(")");
332 },
333 .opt_payload => |opt_ip| {
334 try print(.{
335 .ty = ip.typeOf(opt_ip).toType(),
336 .val = opt_ip.toValue(),
337 }, writer, level - 1, mod);
338 try writer.writeAll(".?");
339 },
340 .elem => |elem| {
341 try print(.{
342 .ty = ip.typeOf(elem.base).toType(),
343 .val = elem.base.toValue(),
344 }, writer, level - 1, mod);
345 try writer.print("[{}]", .{elem.index});
346 },
347 .field => |field| {
348 const container_ty = ip.typeOf(field.base).toType();
349 try print(.{
350 .ty = container_ty,
351 .val = field.base.toValue(),
352 }, writer, level - 1, mod);
353
354 switch (container_ty.zigTypeTag(mod)) {
355 .Struct => {
356 if (container_ty.isTuple(mod)) {
357 try writer.print("[{d}]", .{field.index});
358 }
359 const field_name = container_ty.structFieldName(@intCast(usize, field.index), mod);
360 try writer.print(".{i}", .{field_name.fmt(ip)});
361 },
362 .Union => {
363 const field_name = container_ty.unionFields(mod).keys()[@intCast(usize, field.index)];
364 try writer.print(".{i}", .{field_name.fmt(ip)});
365 },
366 .Pointer => {
367 std.debug.assert(container_ty.isSlice(mod));
368 try writer.writeAll(switch (field.index) {
369 Value.slice_ptr_index => ".ptr",
370 Value.slice_len_index => ".len",
371 else => unreachable,
372 });
373 },
374 else => unreachable,
375 }
376 },
377 }
378 },
379 .opt => |opt| switch (opt.val) {
380 .none => return writer.writeAll("null"),
381 else => |payload| {
382 val = payload.toValue();
383 ty = ty.optionalChild(mod);
384 },
385 },
386 .aggregate => |aggregate| switch (aggregate.storage) {
387 .bytes => |bytes| {
388 // Strip the 0 sentinel off of strings before printing
389 const zero_sent = blk: {
390 const sent = ty.sentinel(mod) orelse break :blk false;
391 break :blk sent.eql(Value.zero_u8, Type.u8, mod);
392 };
393 const str = if (zero_sent) bytes[0 .. bytes.len - 1] else bytes;
394 return writer.print("\"{}\"", .{std.zig.fmtEscapes(str)});
395 },
396 .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod),
397 },
398 .un => |un| {
399 try writer.writeAll(".{ ");
400 if (level > 0) {
401 try print(.{
402 .ty = ty.unionTagTypeHypothetical(mod),
403 .val = un.tag.toValue(),
404 }, writer, level - 1, mod);
405 try writer.writeAll(" = ");
406 try print(.{
407 .ty = ty.unionFieldType(un.tag.toValue(), mod),
408 .val = un.val.toValue(),
409 }, writer, level - 1, mod);
410 } else try writer.writeAll("...");
411 return writer.writeAll(" }");
412 },
413 .memoized_call => unreachable,
437414 },
438 .eu_payload_ptr => {
439 try writer.writeAll("&");
440
441 const data = val.castTag(.eu_payload_ptr).?.data;
442
443 var ty_val: Value.Payload.Ty = .{
444 .base = .{ .tag = .ty },
445 .data = ty,
446 };
415 };
416}
447417
448 try writer.writeAll("@as(");
449 try print(.{
450 .ty = Type.type,
451 .val = Value.initPayload(&ty_val.base),
452 }, writer, level - 1, mod);
418fn printAggregate(
419 ty: Type,
420 val: Value,
421 writer: anytype,
422 level: u8,
423 mod: *Module,
424) (@TypeOf(writer).Error || Allocator.Error)!void {
425 if (level == 0) {
426 return writer.writeAll(".{ ... }");
427 }
428 if (ty.zigTypeTag(mod) == .Struct) {
429 try writer.writeAll(".{");
430 const max_len = @min(ty.structFieldCount(mod), max_aggregate_items);
453431
454 try writer.writeAll(", &(payload of ");
432 for (0..max_len) |i| {
433 if (i != 0) try writer.writeAll(", ");
455434
456 var ptr_ty: Type.Payload.ElemType = .{
457 .base = .{ .tag = .single_mut_pointer },
458 .data = data.container_ty,
435 const field_name = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
436 .struct_type => |x| mod.structPtrUnwrap(x.index).?.fields.keys()[i].toOptional(),
437 .anon_struct_type => |x| if (x.isTuple()) .none else x.names[i].toOptional(),
438 else => unreachable,
459439 };
460440
441 if (field_name.unwrap()) |name| try writer.print(".{} = ", .{name.fmt(&mod.intern_pool)});
461442 try print(.{
462 .ty = Type.initPayload(&ptr_ty.base),
463 .val = data.container_ptr,
443 .ty = ty.structFieldType(i, mod),
444 .val = try val.fieldValue(mod, i),
464445 }, writer, level - 1, mod);
446 }
447 if (ty.structFieldCount(mod) > max_aggregate_items) {
448 try writer.writeAll(", ...");
449 }
450 return writer.writeAll("}");
451 } else {
452 const elem_ty = ty.elemType2(mod);
453 const len = ty.arrayLen(mod);
454
455 if (elem_ty.eql(Type.u8, mod)) str: {
456 const max_len = @intCast(usize, std.math.min(len, max_string_len));
457 var buf: [max_string_len]u8 = undefined;
465458
466 try writer.writeAll("))");
467 return;
468 },
469 .opt_payload_ptr => {
470 const data = val.castTag(.opt_payload_ptr).?.data;
471
472 var ty_val: Value.Payload.Ty = .{
473 .base = .{ .tag = .ty },
474 .data = ty,
475 };
476
477 try writer.writeAll("@as(");
478 try print(.{
479 .ty = Type.type,
480 .val = Value.initPayload(&ty_val.base),
481 }, writer, level - 1, mod);
459 var i: u32 = 0;
460 while (i < max_len) : (i += 1) {
461 const elem = try val.fieldValue(mod, i);
462 if (elem.isUndef(mod)) break :str;
463 buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
464 }
482465
483 try writer.writeAll(", &(payload of ");
466 const truncated = if (len > max_string_len) " (truncated)" else "";
467 return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated });
468 }
484469
485 var ptr_ty: Type.Payload.ElemType = .{
486 .base = .{ .tag = .single_mut_pointer },
487 .data = data.container_ty,
488 };
470 try writer.writeAll(".{ ");
489471
472 const max_len = std.math.min(len, max_aggregate_items);
473 var i: u32 = 0;
474 while (i < max_len) : (i += 1) {
475 if (i != 0) try writer.writeAll(", ");
490476 try print(.{
491 .ty = Type.initPayload(&ptr_ty.base),
492 .val = data.container_ptr,
477 .ty = elem_ty,
478 .val = try val.fieldValue(mod, i),
493479 }, writer, level - 1, mod);
494
495 try writer.writeAll("))");
496 return;
497 },
498
499 // TODO these should not appear in this function
500 .inferred_alloc => return writer.writeAll("(inferred allocation value)"),
501 .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"),
502 .generic_poison_type => return writer.writeAll("(generic poison type)"),
503 .generic_poison => return writer.writeAll("(generic poison)"),
504 .runtime_value => return writer.writeAll("[runtime value]"),
505 };
480 }
481 if (len > max_aggregate_items) {
482 try writer.writeAll(", ...");
483 }
484 return writer.writeAll(" }");
485 }
506486}
src/Zir.zig+97-435
......@@ -19,6 +19,7 @@ const BigIntConst = std.math.big.int.Const;
1919const BigIntMutable = std.math.big.int.Mutable;
2020const Ast = std.zig.Ast;
2121
22const InternPool = @import("InternPool.zig");
2223const Zir = @This();
2324const Type = @import("type.zig").Type;
2425const Value = @import("value.zig").Value;
......@@ -2041,448 +2042,103 @@ pub const Inst = struct {
20412042 /// The position of a ZIR instruction within the `Zir` instructions array.
20422043 pub const Index = u32;
20432044
2044 /// A reference to a TypedValue or ZIR instruction.
2045 /// A reference to ZIR instruction, or to an InternPool index, or neither.
20452046 ///
2046 /// If the Ref has a tag in this enum, it refers to a TypedValue.
2047 ///
2048 /// If the value of a Ref does not have a tag, it refers to a ZIR instruction.
2049 ///
2050 /// The first values after the the last tag refer to ZIR instructions which may
2051 /// be derived by subtracting `typed_value_map.len`.
2052 ///
2053 /// When adding a tag to this enum, consider adding a corresponding entry to
2054 /// `primitives` in astgen.
2047 /// If the integer tag value is < InternPool.static_len, then it
2048 /// corresponds to an InternPool index. Otherwise, this refers to a ZIR
2049 /// instruction.
20552050 ///
20562051 /// The tag type is specified so that it is safe to bitcast between `[]u32`
20572052 /// and `[]Ref`.
20582053 pub const Ref = enum(u32) {
2054 u1_type = @enumToInt(InternPool.Index.u1_type),
2055 u8_type = @enumToInt(InternPool.Index.u8_type),
2056 i8_type = @enumToInt(InternPool.Index.i8_type),
2057 u16_type = @enumToInt(InternPool.Index.u16_type),
2058 i16_type = @enumToInt(InternPool.Index.i16_type),
2059 u29_type = @enumToInt(InternPool.Index.u29_type),
2060 u32_type = @enumToInt(InternPool.Index.u32_type),
2061 i32_type = @enumToInt(InternPool.Index.i32_type),
2062 u64_type = @enumToInt(InternPool.Index.u64_type),
2063 i64_type = @enumToInt(InternPool.Index.i64_type),
2064 u80_type = @enumToInt(InternPool.Index.u80_type),
2065 u128_type = @enumToInt(InternPool.Index.u128_type),
2066 i128_type = @enumToInt(InternPool.Index.i128_type),
2067 usize_type = @enumToInt(InternPool.Index.usize_type),
2068 isize_type = @enumToInt(InternPool.Index.isize_type),
2069 c_char_type = @enumToInt(InternPool.Index.c_char_type),
2070 c_short_type = @enumToInt(InternPool.Index.c_short_type),
2071 c_ushort_type = @enumToInt(InternPool.Index.c_ushort_type),
2072 c_int_type = @enumToInt(InternPool.Index.c_int_type),
2073 c_uint_type = @enumToInt(InternPool.Index.c_uint_type),
2074 c_long_type = @enumToInt(InternPool.Index.c_long_type),
2075 c_ulong_type = @enumToInt(InternPool.Index.c_ulong_type),
2076 c_longlong_type = @enumToInt(InternPool.Index.c_longlong_type),
2077 c_ulonglong_type = @enumToInt(InternPool.Index.c_ulonglong_type),
2078 c_longdouble_type = @enumToInt(InternPool.Index.c_longdouble_type),
2079 f16_type = @enumToInt(InternPool.Index.f16_type),
2080 f32_type = @enumToInt(InternPool.Index.f32_type),
2081 f64_type = @enumToInt(InternPool.Index.f64_type),
2082 f80_type = @enumToInt(InternPool.Index.f80_type),
2083 f128_type = @enumToInt(InternPool.Index.f128_type),
2084 anyopaque_type = @enumToInt(InternPool.Index.anyopaque_type),
2085 bool_type = @enumToInt(InternPool.Index.bool_type),
2086 void_type = @enumToInt(InternPool.Index.void_type),
2087 type_type = @enumToInt(InternPool.Index.type_type),
2088 anyerror_type = @enumToInt(InternPool.Index.anyerror_type),
2089 comptime_int_type = @enumToInt(InternPool.Index.comptime_int_type),
2090 comptime_float_type = @enumToInt(InternPool.Index.comptime_float_type),
2091 noreturn_type = @enumToInt(InternPool.Index.noreturn_type),
2092 anyframe_type = @enumToInt(InternPool.Index.anyframe_type),
2093 null_type = @enumToInt(InternPool.Index.null_type),
2094 undefined_type = @enumToInt(InternPool.Index.undefined_type),
2095 enum_literal_type = @enumToInt(InternPool.Index.enum_literal_type),
2096 atomic_order_type = @enumToInt(InternPool.Index.atomic_order_type),
2097 atomic_rmw_op_type = @enumToInt(InternPool.Index.atomic_rmw_op_type),
2098 calling_convention_type = @enumToInt(InternPool.Index.calling_convention_type),
2099 address_space_type = @enumToInt(InternPool.Index.address_space_type),
2100 float_mode_type = @enumToInt(InternPool.Index.float_mode_type),
2101 reduce_op_type = @enumToInt(InternPool.Index.reduce_op_type),
2102 call_modifier_type = @enumToInt(InternPool.Index.call_modifier_type),
2103 prefetch_options_type = @enumToInt(InternPool.Index.prefetch_options_type),
2104 export_options_type = @enumToInt(InternPool.Index.export_options_type),
2105 extern_options_type = @enumToInt(InternPool.Index.extern_options_type),
2106 type_info_type = @enumToInt(InternPool.Index.type_info_type),
2107 manyptr_u8_type = @enumToInt(InternPool.Index.manyptr_u8_type),
2108 manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type),
2109 manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type),
2110 single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type),
2111 slice_const_u8_type = @enumToInt(InternPool.Index.slice_const_u8_type),
2112 slice_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.slice_const_u8_sentinel_0_type),
2113 anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type),
2114 generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type),
2115 empty_struct_type = @enumToInt(InternPool.Index.empty_struct_type),
2116 undef = @enumToInt(InternPool.Index.undef),
2117 zero = @enumToInt(InternPool.Index.zero),
2118 zero_usize = @enumToInt(InternPool.Index.zero_usize),
2119 zero_u8 = @enumToInt(InternPool.Index.zero_u8),
2120 one = @enumToInt(InternPool.Index.one),
2121 one_usize = @enumToInt(InternPool.Index.one_usize),
2122 one_u8 = @enumToInt(InternPool.Index.one_u8),
2123 four_u8 = @enumToInt(InternPool.Index.four_u8),
2124 negative_one = @enumToInt(InternPool.Index.negative_one),
2125 calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c),
2126 calling_convention_inline = @enumToInt(InternPool.Index.calling_convention_inline),
2127 void_value = @enumToInt(InternPool.Index.void_value),
2128 unreachable_value = @enumToInt(InternPool.Index.unreachable_value),
2129 null_value = @enumToInt(InternPool.Index.null_value),
2130 bool_true = @enumToInt(InternPool.Index.bool_true),
2131 bool_false = @enumToInt(InternPool.Index.bool_false),
2132 empty_struct = @enumToInt(InternPool.Index.empty_struct),
2133 generic_poison = @enumToInt(InternPool.Index.generic_poison),
2134
2135 /// This tag is here to match Air and InternPool, however it is unused
2136 /// for ZIR purposes.
2137 var_args_param_type = @enumToInt(InternPool.Index.var_args_param_type),
20592138 /// This Ref does not correspond to any ZIR instruction or constant
20602139 /// value and may instead be used as a sentinel to indicate null.
2061 none,
2062
2063 u1_type,
2064 u8_type,
2065 i8_type,
2066 u16_type,
2067 i16_type,
2068 u29_type,
2069 u32_type,
2070 i32_type,
2071 u64_type,
2072 i64_type,
2073 u128_type,
2074 i128_type,
2075 usize_type,
2076 isize_type,
2077 c_char_type,
2078 c_short_type,
2079 c_ushort_type,
2080 c_int_type,
2081 c_uint_type,
2082 c_long_type,
2083 c_ulong_type,
2084 c_longlong_type,
2085 c_ulonglong_type,
2086 c_longdouble_type,
2087 f16_type,
2088 f32_type,
2089 f64_type,
2090 f80_type,
2091 f128_type,
2092 anyopaque_type,
2093 bool_type,
2094 void_type,
2095 type_type,
2096 anyerror_type,
2097 comptime_int_type,
2098 comptime_float_type,
2099 noreturn_type,
2100 anyframe_type,
2101 null_type,
2102 undefined_type,
2103 enum_literal_type,
2104 atomic_order_type,
2105 atomic_rmw_op_type,
2106 calling_convention_type,
2107 address_space_type,
2108 float_mode_type,
2109 reduce_op_type,
2110 modifier_type,
2111 prefetch_options_type,
2112 export_options_type,
2113 extern_options_type,
2114 type_info_type,
2115 manyptr_u8_type,
2116 manyptr_const_u8_type,
2117 fn_noreturn_no_args_type,
2118 fn_void_no_args_type,
2119 fn_naked_noreturn_no_args_type,
2120 fn_ccc_void_no_args_type,
2121 single_const_pointer_to_comptime_int_type,
2122 const_slice_u8_type,
2123 anyerror_void_error_union_type,
2124 generic_poison_type,
2125
2126 /// `undefined` (untyped)
2127 undef,
2128 /// `0` (comptime_int)
2129 zero,
2130 /// `1` (comptime_int)
2131 one,
2132 /// `{}`
2133 void_value,
2134 /// `unreachable` (noreturn type)
2135 unreachable_value,
2136 /// `null` (untyped)
2137 null_value,
2138 /// `true`
2139 bool_true,
2140 /// `false`
2141 bool_false,
2142 /// `.{}` (untyped)
2143 empty_struct,
2144 /// `0` (usize)
2145 zero_usize,
2146 /// `1` (usize)
2147 one_usize,
2148 /// `std.builtin.CallingConvention.C`
2149 calling_convention_c,
2150 /// `std.builtin.CallingConvention.Inline`
2151 calling_convention_inline,
2152 /// Used for generic parameters where the type and value
2153 /// is not known until generic function instantiation.
2154 generic_poison,
2155 /// This is a special type for variadic parameters of a function call.
2156 /// Casts to it will validate that the type can be passed to a c
2157 /// calling convention function.
2158 var_args_param,
2159
2140 none = @enumToInt(InternPool.Index.none),
21602141 _,
2161
2162 pub const typed_value_map = std.enums.directEnumArray(Ref, TypedValue, 0, .{
2163 .none = undefined,
2164
2165 .u1_type = .{
2166 .ty = Type.initTag(.type),
2167 .val = Value.initTag(.u1_type),
2168 },
2169 .u8_type = .{
2170 .ty = Type.initTag(.type),
2171 .val = Value.initTag(.u8_type),
2172 },
2173 .i8_type = .{
2174 .ty = Type.initTag(.type),
2175 .val = Value.initTag(.i8_type),
2176 },
2177 .u16_type = .{
2178 .ty = Type.initTag(.type),
2179 .val = Value.initTag(.u16_type),
2180 },
2181 .i16_type = .{
2182 .ty = Type.initTag(.type),
2183 .val = Value.initTag(.i16_type),
2184 },
2185 .u29_type = .{
2186 .ty = Type.initTag(.type),
2187 .val = Value.initTag(.u29_type),
2188 },
2189 .u32_type = .{
2190 .ty = Type.initTag(.type),
2191 .val = Value.initTag(.u32_type),
2192 },
2193 .i32_type = .{
2194 .ty = Type.initTag(.type),
2195 .val = Value.initTag(.i32_type),
2196 },
2197 .u64_type = .{
2198 .ty = Type.initTag(.type),
2199 .val = Value.initTag(.u64_type),
2200 },
2201 .i64_type = .{
2202 .ty = Type.initTag(.type),
2203 .val = Value.initTag(.i64_type),
2204 },
2205 .u128_type = .{
2206 .ty = Type.initTag(.type),
2207 .val = Value.initTag(.u128_type),
2208 },
2209 .i128_type = .{
2210 .ty = Type.initTag(.type),
2211 .val = Value.initTag(.i128_type),
2212 },
2213 .usize_type = .{
2214 .ty = Type.initTag(.type),
2215 .val = Value.initTag(.usize_type),
2216 },
2217 .isize_type = .{
2218 .ty = Type.initTag(.type),
2219 .val = Value.initTag(.isize_type),
2220 },
2221 .c_char_type = .{
2222 .ty = Type.initTag(.type),
2223 .val = Value.initTag(.c_char_type),
2224 },
2225 .c_short_type = .{
2226 .ty = Type.initTag(.type),
2227 .val = Value.initTag(.c_short_type),
2228 },
2229 .c_ushort_type = .{
2230 .ty = Type.initTag(.type),
2231 .val = Value.initTag(.c_ushort_type),
2232 },
2233 .c_int_type = .{
2234 .ty = Type.initTag(.type),
2235 .val = Value.initTag(.c_int_type),
2236 },
2237 .c_uint_type = .{
2238 .ty = Type.initTag(.type),
2239 .val = Value.initTag(.c_uint_type),
2240 },
2241 .c_long_type = .{
2242 .ty = Type.initTag(.type),
2243 .val = Value.initTag(.c_long_type),
2244 },
2245 .c_ulong_type = .{
2246 .ty = Type.initTag(.type),
2247 .val = Value.initTag(.c_ulong_type),
2248 },
2249 .c_longlong_type = .{
2250 .ty = Type.initTag(.type),
2251 .val = Value.initTag(.c_longlong_type),
2252 },
2253 .c_ulonglong_type = .{
2254 .ty = Type.initTag(.type),
2255 .val = Value.initTag(.c_ulonglong_type),
2256 },
2257 .c_longdouble_type = .{
2258 .ty = Type.initTag(.type),
2259 .val = Value.initTag(.c_longdouble_type),
2260 },
2261 .f16_type = .{
2262 .ty = Type.initTag(.type),
2263 .val = Value.initTag(.f16_type),
2264 },
2265 .f32_type = .{
2266 .ty = Type.initTag(.type),
2267 .val = Value.initTag(.f32_type),
2268 },
2269 .f64_type = .{
2270 .ty = Type.initTag(.type),
2271 .val = Value.initTag(.f64_type),
2272 },
2273 .f80_type = .{
2274 .ty = Type.initTag(.type),
2275 .val = Value.initTag(.f80_type),
2276 },
2277 .f128_type = .{
2278 .ty = Type.initTag(.type),
2279 .val = Value.initTag(.f128_type),
2280 },
2281 .anyopaque_type = .{
2282 .ty = Type.initTag(.type),
2283 .val = Value.initTag(.anyopaque_type),
2284 },
2285 .bool_type = .{
2286 .ty = Type.initTag(.type),
2287 .val = Value.initTag(.bool_type),
2288 },
2289 .void_type = .{
2290 .ty = Type.initTag(.type),
2291 .val = Value.initTag(.void_type),
2292 },
2293 .type_type = .{
2294 .ty = Type.initTag(.type),
2295 .val = Value.initTag(.type_type),
2296 },
2297 .anyerror_type = .{
2298 .ty = Type.initTag(.type),
2299 .val = Value.initTag(.anyerror_type),
2300 },
2301 .comptime_int_type = .{
2302 .ty = Type.initTag(.type),
2303 .val = Value.initTag(.comptime_int_type),
2304 },
2305 .comptime_float_type = .{
2306 .ty = Type.initTag(.type),
2307 .val = Value.initTag(.comptime_float_type),
2308 },
2309 .noreturn_type = .{
2310 .ty = Type.initTag(.type),
2311 .val = Value.initTag(.noreturn_type),
2312 },
2313 .anyframe_type = .{
2314 .ty = Type.initTag(.type),
2315 .val = Value.initTag(.anyframe_type),
2316 },
2317 .null_type = .{
2318 .ty = Type.initTag(.type),
2319 .val = Value.initTag(.null_type),
2320 },
2321 .undefined_type = .{
2322 .ty = Type.initTag(.type),
2323 .val = Value.initTag(.undefined_type),
2324 },
2325 .fn_noreturn_no_args_type = .{
2326 .ty = Type.initTag(.type),
2327 .val = Value.initTag(.fn_noreturn_no_args_type),
2328 },
2329 .fn_void_no_args_type = .{
2330 .ty = Type.initTag(.type),
2331 .val = Value.initTag(.fn_void_no_args_type),
2332 },
2333 .fn_naked_noreturn_no_args_type = .{
2334 .ty = Type.initTag(.type),
2335 .val = Value.initTag(.fn_naked_noreturn_no_args_type),
2336 },
2337 .fn_ccc_void_no_args_type = .{
2338 .ty = Type.initTag(.type),
2339 .val = Value.initTag(.fn_ccc_void_no_args_type),
2340 },
2341 .single_const_pointer_to_comptime_int_type = .{
2342 .ty = Type.initTag(.type),
2343 .val = Value.initTag(.single_const_pointer_to_comptime_int_type),
2344 },
2345 .const_slice_u8_type = .{
2346 .ty = Type.initTag(.type),
2347 .val = Value.initTag(.const_slice_u8_type),
2348 },
2349 .anyerror_void_error_union_type = .{
2350 .ty = Type.initTag(.type),
2351 .val = Value.initTag(.anyerror_void_error_union_type),
2352 },
2353 .generic_poison_type = .{
2354 .ty = Type.initTag(.type),
2355 .val = Value.initTag(.generic_poison_type),
2356 },
2357 .enum_literal_type = .{
2358 .ty = Type.initTag(.type),
2359 .val = Value.initTag(.enum_literal_type),
2360 },
2361 .manyptr_u8_type = .{
2362 .ty = Type.initTag(.type),
2363 .val = Value.initTag(.manyptr_u8_type),
2364 },
2365 .manyptr_const_u8_type = .{
2366 .ty = Type.initTag(.type),
2367 .val = Value.initTag(.manyptr_const_u8_type),
2368 },
2369 .atomic_order_type = .{
2370 .ty = Type.initTag(.type),
2371 .val = Value.initTag(.atomic_order_type),
2372 },
2373 .atomic_rmw_op_type = .{
2374 .ty = Type.initTag(.type),
2375 .val = Value.initTag(.atomic_rmw_op_type),
2376 },
2377 .calling_convention_type = .{
2378 .ty = Type.initTag(.type),
2379 .val = Value.initTag(.calling_convention_type),
2380 },
2381 .address_space_type = .{
2382 .ty = Type.initTag(.type),
2383 .val = Value.initTag(.address_space_type),
2384 },
2385 .float_mode_type = .{
2386 .ty = Type.initTag(.type),
2387 .val = Value.initTag(.float_mode_type),
2388 },
2389 .reduce_op_type = .{
2390 .ty = Type.initTag(.type),
2391 .val = Value.initTag(.reduce_op_type),
2392 },
2393 .modifier_type = .{
2394 .ty = Type.initTag(.type),
2395 .val = Value.initTag(.modifier_type),
2396 },
2397 .prefetch_options_type = .{
2398 .ty = Type.initTag(.type),
2399 .val = Value.initTag(.prefetch_options_type),
2400 },
2401 .export_options_type = .{
2402 .ty = Type.initTag(.type),
2403 .val = Value.initTag(.export_options_type),
2404 },
2405 .extern_options_type = .{
2406 .ty = Type.initTag(.type),
2407 .val = Value.initTag(.extern_options_type),
2408 },
2409 .type_info_type = .{
2410 .ty = Type.initTag(.type),
2411 .val = Value.initTag(.type_info_type),
2412 },
2413
2414 .undef = .{
2415 .ty = Type.initTag(.undefined),
2416 .val = Value.initTag(.undef),
2417 },
2418 .zero = .{
2419 .ty = Type.initTag(.comptime_int),
2420 .val = Value.initTag(.zero),
2421 },
2422 .zero_usize = .{
2423 .ty = Type.initTag(.usize),
2424 .val = Value.initTag(.zero),
2425 },
2426 .one = .{
2427 .ty = Type.initTag(.comptime_int),
2428 .val = Value.initTag(.one),
2429 },
2430 .one_usize = .{
2431 .ty = Type.initTag(.usize),
2432 .val = Value.initTag(.one),
2433 },
2434 .void_value = .{
2435 .ty = Type.initTag(.void),
2436 .val = Value.initTag(.void_value),
2437 },
2438 .unreachable_value = .{
2439 .ty = Type.initTag(.noreturn),
2440 .val = Value.initTag(.unreachable_value),
2441 },
2442 .null_value = .{
2443 .ty = Type.initTag(.null),
2444 .val = Value.initTag(.null_value),
2445 },
2446 .bool_true = .{
2447 .ty = Type.initTag(.bool),
2448 .val = Value.initTag(.bool_true),
2449 },
2450 .bool_false = .{
2451 .ty = Type.initTag(.bool),
2452 .val = Value.initTag(.bool_false),
2453 },
2454 .empty_struct = .{
2455 .ty = Type.initTag(.empty_struct_literal),
2456 .val = Value.initTag(.empty_struct_value),
2457 },
2458 .calling_convention_c = .{
2459 .ty = Type.initTag(.calling_convention),
2460 .val = .{ .ptr_otherwise = &calling_convention_c_payload.base },
2461 },
2462 .calling_convention_inline = .{
2463 .ty = Type.initTag(.calling_convention),
2464 .val = .{ .ptr_otherwise = &calling_convention_inline_payload.base },
2465 },
2466 .generic_poison = .{
2467 .ty = Type.initTag(.generic_poison),
2468 .val = Value.initTag(.generic_poison),
2469 },
2470 .var_args_param = undefined,
2471 });
2472 };
2473
2474 /// We would like this to be const but `Value` wants a mutable pointer for
2475 /// its payload field. Nothing should mutate this though.
2476 var calling_convention_c_payload: Value.Payload.U32 = .{
2477 .base = .{ .tag = .enum_field_index },
2478 .data = @enumToInt(std.builtin.CallingConvention.C),
2479 };
2480
2481 /// We would like this to be const but `Value` wants a mutable pointer for
2482 /// its payload field. Nothing should mutate this though.
2483 var calling_convention_inline_payload: Value.Payload.U32 = .{
2484 .base = .{ .tag = .enum_field_index },
2485 .data = @enumToInt(std.builtin.CallingConvention.Inline),
24862142 };
24872143
24882144 /// All instructions have an 8-byte payload, which is contained within
......@@ -4163,13 +3819,14 @@ pub fn getFnInfo(zir: Zir, fn_inst: Inst.Index) FnInfo {
41633819 };
41643820}
41653821
4166const ref_start_index: u32 = Inst.Ref.typed_value_map.len;
3822pub const ref_start_index: u32 = InternPool.static_len;
41673823
41683824pub fn indexToRef(inst: Inst.Index) Inst.Ref {
41693825 return @intToEnum(Inst.Ref, ref_start_index + inst);
41703826}
41713827
41723828pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
3829 assert(inst != .none);
41733830 const ref_int = @enumToInt(inst);
41743831 if (ref_int >= ref_start_index) {
41753832 return ref_int - ref_start_index;
......@@ -4177,3 +3834,8 @@ pub fn refToIndex(inst: Inst.Ref) ?Inst.Index {
41773834 return null;
41783835 }
41793836}
3837
3838pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
3839 if (inst == .none) return null;
3840 return refToIndex(inst);
3841}
src/arch/aarch64/CodeGen.zig+372-350
......@@ -328,7 +328,7 @@ const Self = @This();
328328pub fn generate(
329329 bin_file: *link.File,
330330 src_loc: Module.SrcLoc,
331 module_fn: *Module.Fn,
331 module_fn_index: Module.Fn.Index,
332332 air: Air,
333333 liveness: Liveness,
334334 code: *std.ArrayList(u8),
......@@ -339,6 +339,7 @@ pub fn generate(
339339 }
340340
341341 const mod = bin_file.options.module.?;
342 const module_fn = mod.funcPtr(module_fn_index);
342343 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
343344 assert(fn_owner_decl.has_tv);
344345 const fn_type = fn_owner_decl.ty;
......@@ -471,7 +472,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
471472}
472473
473474fn gen(self: *Self) !void {
474 const cc = self.fn_type.fnCallingConvention();
475 const mod = self.bin_file.options.module.?;
476 const cc = self.fn_type.fnCallingConvention(mod);
475477 if (cc != .Naked) {
476478 // stp fp, lr, [sp, #-16]!
477479 _ = try self.addInst(.{
......@@ -520,10 +522,10 @@ fn gen(self: *Self) !void {
520522 const inst = self.air.getMainBody()[arg_index];
521523 assert(self.air.instructions.items(.tag)[inst] == .arg);
522524
523 const ty = self.air.typeOfIndex(inst);
525 const ty = self.typeOfIndex(inst);
524526
525 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
526 const abi_align = ty.abiAlignment(self.target.*);
527 const abi_size = @intCast(u32, ty.abiSize(mod));
528 const abi_align = ty.abiAlignment(mod);
527529 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
528530 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
529531
......@@ -652,13 +654,14 @@ fn gen(self: *Self) !void {
652654}
653655
654656fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
657 const mod = self.bin_file.options.module.?;
658 const ip = &mod.intern_pool;
655659 const air_tags = self.air.instructions.items(.tag);
656660
657661 for (body) |inst| {
658662 // TODO: remove now-redundant isUnused calls from AIR handler functions
659 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
663 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
660664 continue;
661 }
662665
663666 const old_air_bookkeeping = self.air_bookkeeping;
664667 try self.ensureProcessDeathCapacity(Liveness.bpi);
......@@ -842,8 +845,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
842845 .ptr_elem_val => try self.airPtrElemVal(inst),
843846 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
844847
845 .constant => unreachable, // excluded from function bodies
846 .const_ty => unreachable, // excluded from function bodies
848 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
847849 .unreach => self.finishAirBookkeeping(),
848850
849851 .optional_payload => try self.airOptionalPayload(inst),
......@@ -916,8 +918,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
916918
917919/// Asserts there is already capacity to insert into top branch inst_table.
918920fn processDeath(self: *Self, inst: Air.Inst.Index) void {
919 const air_tags = self.air.instructions.items(.tag);
920 if (air_tags[inst] == .constant) return; // Constants are immortal.
921 assert(self.air.instructions.items(.tag)[inst] != .interned);
921922 // When editing this function, note that the logic must synchronize with `reuseOperand`.
922923 const prev_value = self.getResolvedInstValue(inst);
923924 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -951,8 +952,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
951952 tomb_bits >>= 1;
952953 if (!dies) continue;
953954 const op_int = @enumToInt(op);
954 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;
955 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
955 if (op_int < Air.ref_start_index) continue;
956 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
956957 self.processDeath(op_index);
957958 }
958959 const is_used = @truncate(u1, tomb_bits) == 0;
......@@ -1026,31 +1027,31 @@ fn allocMem(
10261027
10271028/// Use a pointer instruction as the basis for allocating stack memory.
10281029fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
1029 const elem_ty = self.air.typeOfIndex(inst).elemType();
1030 const mod = self.bin_file.options.module.?;
1031 const elem_ty = self.typeOfIndex(inst).childType(mod);
10301032
1031 if (!elem_ty.hasRuntimeBits()) {
1033 if (!elem_ty.hasRuntimeBits(mod)) {
10321034 // return the stack offset 0. Stack offset 0 will be where all
10331035 // zero-sized stack allocations live as non-zero-sized
10341036 // allocations will always have an offset > 0.
10351037 return @as(u32, 0);
10361038 }
10371039
1038 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
1039 const mod = self.bin_file.options.module.?;
1040 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
10401041 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
10411042 };
10421043 // TODO swap this for inst.ty.ptrAlign
1043 const abi_align = elem_ty.abiAlignment(self.target.*);
1044 const abi_align = elem_ty.abiAlignment(mod);
10441045
10451046 return self.allocMem(abi_size, abi_align, inst);
10461047}
10471048
10481049fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {
1049 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
1050 const mod = self.bin_file.options.module.?;
1050 const mod = self.bin_file.options.module.?;
1051 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
10511052 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
10521053 };
1053 const abi_align = elem_ty.abiAlignment(self.target.*);
1054 const abi_align = elem_ty.abiAlignment(mod);
10541055
10551056 if (reg_ok) {
10561057 // Make sure the type can fit in a register before we try to allocate one.
......@@ -1066,7 +1067,7 @@ fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst
10661067}
10671068
10681069pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
1069 const stack_mcv = try self.allocRegOrMem(self.air.typeOfIndex(inst), false, inst);
1070 const stack_mcv = try self.allocRegOrMem(self.typeOfIndex(inst), false, inst);
10701071 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
10711072
10721073 const reg_mcv = self.getResolvedInstValue(inst);
......@@ -1078,14 +1079,14 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
10781079
10791080 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
10801081 try branch.inst_table.put(self.gpa, inst, stack_mcv);
1081 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
1082 try self.genSetStack(self.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
10821083}
10831084
10841085/// Save the current instruction stored in the compare flags if
10851086/// occupied
10861087fn spillCompareFlagsIfOccupied(self: *Self) !void {
10871088 if (self.compare_flags_inst) |inst_to_save| {
1088 const ty = self.air.typeOfIndex(inst_to_save);
1089 const ty = self.typeOfIndex(inst_to_save);
10891090 const mcv = self.getResolvedInstValue(inst_to_save);
10901091 const new_mcv = switch (mcv) {
10911092 .compare_flags => try self.allocRegOrMem(ty, true, inst_to_save),
......@@ -1093,7 +1094,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
10931094 else => unreachable, // mcv doesn't occupy the compare flags
10941095 };
10951096
1096 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
1097 try self.setRegOrMem(self.typeOfIndex(inst_to_save), new_mcv, mcv);
10971098 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
10981099
10991100 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -1125,9 +1126,9 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
11251126/// This can have a side effect of spilling instructions to the stack to free up a register.
11261127fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
11271128 const raw_reg = try self.register_manager.allocReg(reg_owner, gp);
1128 const ty = self.air.typeOfIndex(reg_owner);
1129 const ty = self.typeOfIndex(reg_owner);
11291130 const reg = self.registerAlias(raw_reg, ty);
1130 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
1131 try self.genSetReg(self.typeOfIndex(reg_owner), reg, mcv);
11311132 return MCValue{ .register = reg };
11321133}
11331134
......@@ -1137,17 +1138,14 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
11371138}
11381139
11391140fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1141 const mod = self.bin_file.options.module.?;
11401142 const result: MCValue = switch (self.ret_mcv) {
11411143 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },
11421144 .stack_offset => blk: {
11431145 // self.ret_mcv is an address to where this function
11441146 // should store its result into
1145 const ret_ty = self.fn_type.fnReturnType();
1146 var ptr_ty_payload: Type.Payload.ElemType = .{
1147 .base = .{ .tag = .single_mut_pointer },
1148 .data = ret_ty,
1149 };
1150 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
1147 const ret_ty = self.fn_type.fnReturnType(mod);
1148 const ptr_ty = try mod.singleMutPtrType(ret_ty);
11511149
11521150 // addr_reg will contain the address of where to store the
11531151 // result into
......@@ -1177,13 +1175,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
11771175 if (self.liveness.isUnused(inst))
11781176 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
11791177
1178 const mod = self.bin_file.options.module.?;
11801179 const operand = ty_op.operand;
11811180 const operand_mcv = try self.resolveInst(operand);
1182 const operand_ty = self.air.typeOf(operand);
1183 const operand_info = operand_ty.intInfo(self.target.*);
1181 const operand_ty = self.typeOf(operand);
1182 const operand_info = operand_ty.intInfo(mod);
11841183
1185 const dest_ty = self.air.typeOfIndex(inst);
1186 const dest_info = dest_ty.intInfo(self.target.*);
1184 const dest_ty = self.typeOfIndex(inst);
1185 const dest_info = dest_ty.intInfo(mod);
11871186
11881187 const result: MCValue = result: {
11891188 const operand_lock: ?RegisterLock = switch (operand_mcv) {
......@@ -1199,14 +1198,14 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
11991198
12001199 if (dest_info.bits > operand_info.bits) {
12011200 const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst);
1202 try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated);
1201 try self.setRegOrMem(self.typeOfIndex(inst), dest_mcv, truncated);
12031202 break :result dest_mcv;
12041203 } else {
12051204 if (self.reuseOperand(inst, operand, 0, truncated)) {
12061205 break :result truncated;
12071206 } else {
12081207 const dest_mcv = try self.allocRegOrMem(dest_ty, true, inst);
1209 try self.setRegOrMem(self.air.typeOfIndex(inst), dest_mcv, truncated);
1208 try self.setRegOrMem(self.typeOfIndex(inst), dest_mcv, truncated);
12101209 break :result dest_mcv;
12111210 }
12121211 }
......@@ -1257,8 +1256,9 @@ fn trunc(
12571256 operand_ty: Type,
12581257 dest_ty: Type,
12591258) !MCValue {
1260 const info_a = operand_ty.intInfo(self.target.*);
1261 const info_b = dest_ty.intInfo(self.target.*);
1259 const mod = self.bin_file.options.module.?;
1260 const info_a = operand_ty.intInfo(mod);
1261 const info_b = dest_ty.intInfo(mod);
12621262
12631263 if (info_b.bits <= 64) {
12641264 const operand_reg = switch (operand) {
......@@ -1300,8 +1300,8 @@ fn trunc(
13001300fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
13011301 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
13021302 const operand = try self.resolveInst(ty_op.operand);
1303 const operand_ty = self.air.typeOf(ty_op.operand);
1304 const dest_ty = self.air.typeOfIndex(inst);
1303 const operand_ty = self.typeOf(ty_op.operand);
1304 const dest_ty = self.typeOfIndex(inst);
13051305
13061306 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
13071307 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);
......@@ -1319,15 +1319,16 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
13191319
13201320fn airNot(self: *Self, inst: Air.Inst.Index) !void {
13211321 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1322 const mod = self.bin_file.options.module.?;
13221323 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
13231324 const operand = try self.resolveInst(ty_op.operand);
1324 const operand_ty = self.air.typeOf(ty_op.operand);
1325 const operand_ty = self.typeOf(ty_op.operand);
13251326 switch (operand) {
13261327 .dead => unreachable,
13271328 .unreach => unreachable,
13281329 .compare_flags => |cond| break :result MCValue{ .compare_flags = cond.negate() },
13291330 else => {
1330 switch (operand_ty.zigTypeTag()) {
1331 switch (operand_ty.zigTypeTag(mod)) {
13311332 .Bool => {
13321333 // TODO convert this to mvn + and
13331334 const op_reg = switch (operand) {
......@@ -1361,7 +1362,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
13611362 },
13621363 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
13631364 .Int => {
1364 const int_info = operand_ty.intInfo(self.target.*);
1365 const int_info = operand_ty.intInfo(mod);
13651366 if (int_info.bits <= 64) {
13661367 const op_reg = switch (operand) {
13671368 .register => |r| r,
......@@ -1413,13 +1414,13 @@ fn minMax(
14131414 rhs_ty: Type,
14141415 maybe_inst: ?Air.Inst.Index,
14151416) !MCValue {
1416 switch (lhs_ty.zigTypeTag()) {
1417 const mod = self.bin_file.options.module.?;
1418 switch (lhs_ty.zigTypeTag(mod)) {
14171419 .Float => return self.fail("TODO ARM min/max on floats", .{}),
14181420 .Vector => return self.fail("TODO ARM min/max on vectors", .{}),
14191421 .Int => {
1420 const mod = self.bin_file.options.module.?;
14211422 assert(lhs_ty.eql(rhs_ty, mod));
1422 const int_info = lhs_ty.intInfo(self.target.*);
1423 const int_info = lhs_ty.intInfo(mod);
14231424 if (int_info.bits <= 64) {
14241425 var lhs_reg: Register = undefined;
14251426 var rhs_reg: Register = undefined;
......@@ -1488,8 +1489,8 @@ fn minMax(
14881489fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
14891490 const tag = self.air.instructions.items(.tag)[inst];
14901491 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1491 const lhs_ty = self.air.typeOf(bin_op.lhs);
1492 const rhs_ty = self.air.typeOf(bin_op.rhs);
1492 const lhs_ty = self.typeOf(bin_op.lhs);
1493 const rhs_ty = self.typeOf(bin_op.rhs);
14931494
14941495 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
14951496 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
......@@ -1508,9 +1509,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
15081509 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
15091510 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
15101511 const ptr = try self.resolveInst(bin_op.lhs);
1511 const ptr_ty = self.air.typeOf(bin_op.lhs);
1512 const ptr_ty = self.typeOf(bin_op.lhs);
15121513 const len = try self.resolveInst(bin_op.rhs);
1513 const len_ty = self.air.typeOf(bin_op.rhs);
1514 const len_ty = self.typeOf(bin_op.rhs);
15141515
15151516 const ptr_bits = self.target.ptrBitWidth();
15161517 const ptr_bytes = @divExact(ptr_bits, 8);
......@@ -1907,12 +1908,12 @@ fn addSub(
19071908 maybe_inst: ?Air.Inst.Index,
19081909) InnerError!MCValue {
19091910 const mod = self.bin_file.options.module.?;
1910 switch (lhs_ty.zigTypeTag()) {
1911 switch (lhs_ty.zigTypeTag(mod)) {
19111912 .Float => return self.fail("TODO binary operations on floats", .{}),
19121913 .Vector => return self.fail("TODO binary operations on vectors", .{}),
19131914 .Int => {
19141915 assert(lhs_ty.eql(rhs_ty, mod));
1915 const int_info = lhs_ty.intInfo(self.target.*);
1916 const int_info = lhs_ty.intInfo(mod);
19161917 if (int_info.bits <= 64) {
19171918 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
19181919 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
......@@ -1968,11 +1969,11 @@ fn mul(
19681969 maybe_inst: ?Air.Inst.Index,
19691970) InnerError!MCValue {
19701971 const mod = self.bin_file.options.module.?;
1971 switch (lhs_ty.zigTypeTag()) {
1972 switch (lhs_ty.zigTypeTag(mod)) {
19721973 .Vector => return self.fail("TODO binary operations on vectors", .{}),
19731974 .Int => {
19741975 assert(lhs_ty.eql(rhs_ty, mod));
1975 const int_info = lhs_ty.intInfo(self.target.*);
1976 const int_info = lhs_ty.intInfo(mod);
19761977 if (int_info.bits <= 64) {
19771978 // TODO add optimisations for multiplication
19781979 // with immediates, for example a * 2 can be
......@@ -1999,7 +2000,8 @@ fn divFloat(
19992000 _ = rhs_ty;
20002001 _ = maybe_inst;
20012002
2002 switch (lhs_ty.zigTypeTag()) {
2003 const mod = self.bin_file.options.module.?;
2004 switch (lhs_ty.zigTypeTag(mod)) {
20032005 .Float => return self.fail("TODO div_float", .{}),
20042006 .Vector => return self.fail("TODO div_float on vectors", .{}),
20052007 else => unreachable,
......@@ -2015,12 +2017,12 @@ fn divTrunc(
20152017 maybe_inst: ?Air.Inst.Index,
20162018) InnerError!MCValue {
20172019 const mod = self.bin_file.options.module.?;
2018 switch (lhs_ty.zigTypeTag()) {
2020 switch (lhs_ty.zigTypeTag(mod)) {
20192021 .Float => return self.fail("TODO div on floats", .{}),
20202022 .Vector => return self.fail("TODO div on vectors", .{}),
20212023 .Int => {
20222024 assert(lhs_ty.eql(rhs_ty, mod));
2023 const int_info = lhs_ty.intInfo(self.target.*);
2025 const int_info = lhs_ty.intInfo(mod);
20242026 if (int_info.bits <= 64) {
20252027 switch (int_info.signedness) {
20262028 .signed => {
......@@ -2049,12 +2051,12 @@ fn divFloor(
20492051 maybe_inst: ?Air.Inst.Index,
20502052) InnerError!MCValue {
20512053 const mod = self.bin_file.options.module.?;
2052 switch (lhs_ty.zigTypeTag()) {
2054 switch (lhs_ty.zigTypeTag(mod)) {
20532055 .Float => return self.fail("TODO div on floats", .{}),
20542056 .Vector => return self.fail("TODO div on vectors", .{}),
20552057 .Int => {
20562058 assert(lhs_ty.eql(rhs_ty, mod));
2057 const int_info = lhs_ty.intInfo(self.target.*);
2059 const int_info = lhs_ty.intInfo(mod);
20582060 if (int_info.bits <= 64) {
20592061 switch (int_info.signedness) {
20602062 .signed => {
......@@ -2082,12 +2084,12 @@ fn divExact(
20822084 maybe_inst: ?Air.Inst.Index,
20832085) InnerError!MCValue {
20842086 const mod = self.bin_file.options.module.?;
2085 switch (lhs_ty.zigTypeTag()) {
2087 switch (lhs_ty.zigTypeTag(mod)) {
20862088 .Float => return self.fail("TODO div on floats", .{}),
20872089 .Vector => return self.fail("TODO div on vectors", .{}),
20882090 .Int => {
20892091 assert(lhs_ty.eql(rhs_ty, mod));
2090 const int_info = lhs_ty.intInfo(self.target.*);
2092 const int_info = lhs_ty.intInfo(mod);
20912093 if (int_info.bits <= 64) {
20922094 switch (int_info.signedness) {
20932095 .signed => {
......@@ -2118,12 +2120,12 @@ fn rem(
21182120 _ = maybe_inst;
21192121
21202122 const mod = self.bin_file.options.module.?;
2121 switch (lhs_ty.zigTypeTag()) {
2123 switch (lhs_ty.zigTypeTag(mod)) {
21222124 .Float => return self.fail("TODO rem/mod on floats", .{}),
21232125 .Vector => return self.fail("TODO rem/mod on vectors", .{}),
21242126 .Int => {
21252127 assert(lhs_ty.eql(rhs_ty, mod));
2126 const int_info = lhs_ty.intInfo(self.target.*);
2128 const int_info = lhs_ty.intInfo(mod);
21272129 if (int_info.bits <= 64) {
21282130 var lhs_reg: Register = undefined;
21292131 var rhs_reg: Register = undefined;
......@@ -2188,7 +2190,8 @@ fn modulo(
21882190 _ = rhs_ty;
21892191 _ = maybe_inst;
21902192
2191 switch (lhs_ty.zigTypeTag()) {
2193 const mod = self.bin_file.options.module.?;
2194 switch (lhs_ty.zigTypeTag(mod)) {
21922195 .Float => return self.fail("TODO mod on floats", .{}),
21932196 .Vector => return self.fail("TODO mod on vectors", .{}),
21942197 .Int => return self.fail("TODO mod on ints", .{}),
......@@ -2205,10 +2208,11 @@ fn wrappingArithmetic(
22052208 rhs_ty: Type,
22062209 maybe_inst: ?Air.Inst.Index,
22072210) InnerError!MCValue {
2208 switch (lhs_ty.zigTypeTag()) {
2211 const mod = self.bin_file.options.module.?;
2212 switch (lhs_ty.zigTypeTag(mod)) {
22092213 .Vector => return self.fail("TODO binary operations on vectors", .{}),
22102214 .Int => {
2211 const int_info = lhs_ty.intInfo(self.target.*);
2215 const int_info = lhs_ty.intInfo(mod);
22122216 if (int_info.bits <= 64) {
22132217 // Generate an add/sub/mul
22142218 const result: MCValue = switch (tag) {
......@@ -2240,11 +2244,11 @@ fn bitwise(
22402244 maybe_inst: ?Air.Inst.Index,
22412245) InnerError!MCValue {
22422246 const mod = self.bin_file.options.module.?;
2243 switch (lhs_ty.zigTypeTag()) {
2247 switch (lhs_ty.zigTypeTag(mod)) {
22442248 .Vector => return self.fail("TODO binary operations on vectors", .{}),
22452249 .Int => {
22462250 assert(lhs_ty.eql(rhs_ty, mod));
2247 const int_info = lhs_ty.intInfo(self.target.*);
2251 const int_info = lhs_ty.intInfo(mod);
22482252 if (int_info.bits <= 64) {
22492253 // TODO implement bitwise operations with immediates
22502254 const mir_tag: Mir.Inst.Tag = switch (tag) {
......@@ -2274,10 +2278,11 @@ fn shiftExact(
22742278) InnerError!MCValue {
22752279 _ = rhs_ty;
22762280
2277 switch (lhs_ty.zigTypeTag()) {
2281 const mod = self.bin_file.options.module.?;
2282 switch (lhs_ty.zigTypeTag(mod)) {
22782283 .Vector => return self.fail("TODO binary operations on vectors", .{}),
22792284 .Int => {
2280 const int_info = lhs_ty.intInfo(self.target.*);
2285 const int_info = lhs_ty.intInfo(mod);
22812286 if (int_info.bits <= 64) {
22822287 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
22832288
......@@ -2323,10 +2328,11 @@ fn shiftNormal(
23232328 rhs_ty: Type,
23242329 maybe_inst: ?Air.Inst.Index,
23252330) InnerError!MCValue {
2326 switch (lhs_ty.zigTypeTag()) {
2331 const mod = self.bin_file.options.module.?;
2332 switch (lhs_ty.zigTypeTag(mod)) {
23272333 .Vector => return self.fail("TODO binary operations on vectors", .{}),
23282334 .Int => {
2329 const int_info = lhs_ty.intInfo(self.target.*);
2335 const int_info = lhs_ty.intInfo(mod);
23302336 if (int_info.bits <= 64) {
23312337 // Generate a shl_exact/shr_exact
23322338 const result: MCValue = switch (tag) {
......@@ -2362,7 +2368,8 @@ fn booleanOp(
23622368 rhs_ty: Type,
23632369 maybe_inst: ?Air.Inst.Index,
23642370) InnerError!MCValue {
2365 switch (lhs_ty.zigTypeTag()) {
2371 const mod = self.bin_file.options.module.?;
2372 switch (lhs_ty.zigTypeTag(mod)) {
23662373 .Bool => {
23672374 assert((try lhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema
23682375 assert((try rhs_bind.resolveToImmediate(self)) == null); // should have been handled by Sema
......@@ -2388,17 +2395,17 @@ fn ptrArithmetic(
23882395 rhs_ty: Type,
23892396 maybe_inst: ?Air.Inst.Index,
23902397) InnerError!MCValue {
2391 switch (lhs_ty.zigTypeTag()) {
2398 const mod = self.bin_file.options.module.?;
2399 switch (lhs_ty.zigTypeTag(mod)) {
23922400 .Pointer => {
2393 const mod = self.bin_file.options.module.?;
23942401 assert(rhs_ty.eql(Type.usize, mod));
23952402
23962403 const ptr_ty = lhs_ty;
2397 const elem_ty = switch (ptr_ty.ptrSize()) {
2398 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
2399 else => ptr_ty.childType(),
2404 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
2405 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
2406 else => ptr_ty.childType(mod),
24002407 };
2401 const elem_size = elem_ty.abiSize(self.target.*);
2408 const elem_size = elem_ty.abiSize(mod);
24022409
24032410 const base_tag: Air.Inst.Tag = switch (tag) {
24042411 .ptr_add => .add,
......@@ -2426,8 +2433,8 @@ fn ptrArithmetic(
24262433
24272434fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
24282435 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2429 const lhs_ty = self.air.typeOf(bin_op.lhs);
2430 const rhs_ty = self.air.typeOf(bin_op.rhs);
2436 const lhs_ty = self.typeOf(bin_op.lhs);
2437 const rhs_ty = self.typeOf(bin_op.rhs);
24312438
24322439 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
24332440 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
......@@ -2477,8 +2484,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
24772484fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
24782485 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
24792486 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2480 const lhs_ty = self.air.typeOf(bin_op.lhs);
2481 const rhs_ty = self.air.typeOf(bin_op.rhs);
2487 const lhs_ty = self.typeOf(bin_op.lhs);
2488 const rhs_ty = self.typeOf(bin_op.rhs);
24822489
24832490 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
24842491 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
......@@ -2511,23 +2518,23 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
25112518 const tag = self.air.instructions.items(.tag)[inst];
25122519 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
25132520 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2521 const mod = self.bin_file.options.module.?;
25142522 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
25152523 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
25162524 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2517 const lhs_ty = self.air.typeOf(extra.lhs);
2518 const rhs_ty = self.air.typeOf(extra.rhs);
2525 const lhs_ty = self.typeOf(extra.lhs);
2526 const rhs_ty = self.typeOf(extra.rhs);
25192527
2520 const tuple_ty = self.air.typeOfIndex(inst);
2521 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
2522 const tuple_align = tuple_ty.abiAlignment(self.target.*);
2523 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
2528 const tuple_ty = self.typeOfIndex(inst);
2529 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
2530 const tuple_align = tuple_ty.abiAlignment(mod);
2531 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
25242532
2525 switch (lhs_ty.zigTypeTag()) {
2533 switch (lhs_ty.zigTypeTag(mod)) {
25262534 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
25272535 .Int => {
2528 const mod = self.bin_file.options.module.?;
25292536 assert(lhs_ty.eql(rhs_ty, mod));
2530 const int_info = lhs_ty.intInfo(self.target.*);
2537 const int_info = lhs_ty.intInfo(mod);
25312538 switch (int_info.bits) {
25322539 1...31, 33...63 => {
25332540 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
......@@ -2565,7 +2572,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
25652572 });
25662573
25672574 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
2568 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
2575 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
25692576
25702577 break :result MCValue{ .stack_offset = stack_offset };
25712578 },
......@@ -2639,24 +2646,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
26392646 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
26402647 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
26412648 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2649 const mod = self.bin_file.options.module.?;
26422650 const result: MCValue = result: {
2643 const mod = self.bin_file.options.module.?;
2644
26452651 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
26462652 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2647 const lhs_ty = self.air.typeOf(extra.lhs);
2648 const rhs_ty = self.air.typeOf(extra.rhs);
2653 const lhs_ty = self.typeOf(extra.lhs);
2654 const rhs_ty = self.typeOf(extra.rhs);
26492655
2650 const tuple_ty = self.air.typeOfIndex(inst);
2651 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
2652 const tuple_align = tuple_ty.abiAlignment(self.target.*);
2653 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
2656 const tuple_ty = self.typeOfIndex(inst);
2657 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
2658 const tuple_align = tuple_ty.abiAlignment(mod);
2659 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
26542660
2655 switch (lhs_ty.zigTypeTag()) {
2661 switch (lhs_ty.zigTypeTag(mod)) {
26562662 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
26572663 .Int => {
26582664 assert(lhs_ty.eql(rhs_ty, mod));
2659 const int_info = lhs_ty.intInfo(self.target.*);
2665 const int_info = lhs_ty.intInfo(mod);
26602666 if (int_info.bits <= 32) {
26612667 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
26622668
......@@ -2709,7 +2715,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
27092715 }
27102716
27112717 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
2712 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
2718 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
27132719
27142720 break :result MCValue{ .stack_offset = stack_offset };
27152721 } else if (int_info.bits <= 64) {
......@@ -2849,7 +2855,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
28492855 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
28502856
28512857 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
2852 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
2858 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
28532859
28542860 break :result MCValue{ .stack_offset = stack_offset };
28552861 } else return self.fail("TODO implement mul_with_overflow for integers > u64/i64", .{});
......@@ -2864,21 +2870,22 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
28642870 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
28652871 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
28662872 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
2873 const mod = self.bin_file.options.module.?;
28672874 const result: MCValue = result: {
28682875 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
28692876 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
2870 const lhs_ty = self.air.typeOf(extra.lhs);
2871 const rhs_ty = self.air.typeOf(extra.rhs);
2877 const lhs_ty = self.typeOf(extra.lhs);
2878 const rhs_ty = self.typeOf(extra.rhs);
28722879
2873 const tuple_ty = self.air.typeOfIndex(inst);
2874 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
2875 const tuple_align = tuple_ty.abiAlignment(self.target.*);
2876 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
2880 const tuple_ty = self.typeOfIndex(inst);
2881 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
2882 const tuple_align = tuple_ty.abiAlignment(mod);
2883 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
28772884
2878 switch (lhs_ty.zigTypeTag()) {
2885 switch (lhs_ty.zigTypeTag(mod)) {
28792886 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
28802887 .Int => {
2881 const int_info = lhs_ty.intInfo(self.target.*);
2888 const int_info = lhs_ty.intInfo(mod);
28822889 if (int_info.bits <= 64) {
28832890 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
28842891
......@@ -2981,7 +2988,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
29812988 });
29822989
29832990 try self.genSetStack(lhs_ty, stack_offset, .{ .register = dest_reg });
2984 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
2991 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .compare_flags = .ne });
29852992
29862993 break :result MCValue{ .stack_offset = stack_offset };
29872994 } else {
......@@ -3003,7 +3010,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
30033010fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
30043011 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
30053012 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3006 const optional_ty = self.air.typeOf(ty_op.operand);
3013 const optional_ty = self.typeOf(ty_op.operand);
30073014 const mcv = try self.resolveInst(ty_op.operand);
30083015 break :result try self.optionalPayload(inst, mcv, optional_ty);
30093016 };
......@@ -3011,10 +3018,10 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
30113018}
30123019
30133020fn optionalPayload(self: *Self, inst: Air.Inst.Index, mcv: MCValue, optional_ty: Type) !MCValue {
3014 var opt_buf: Type.Payload.ElemType = undefined;
3015 const payload_ty = optional_ty.optionalChild(&opt_buf);
3016 if (!payload_ty.hasRuntimeBits()) return MCValue.none;
3017 if (optional_ty.isPtrLikeOptional()) {
3021 const mod = self.bin_file.options.module.?;
3022 const payload_ty = optional_ty.optionalChild(mod);
3023 if (!payload_ty.hasRuntimeBits(mod)) return MCValue.none;
3024 if (optional_ty.isPtrLikeOptional(mod)) {
30183025 // TODO should we reuse the operand here?
30193026 const raw_reg = try self.register_manager.allocReg(inst, gp);
30203027 const reg = self.registerAlias(raw_reg, payload_ty);
......@@ -3055,16 +3062,17 @@ fn errUnionErr(
30553062 error_union_ty: Type,
30563063 maybe_inst: ?Air.Inst.Index,
30573064) !MCValue {
3058 const err_ty = error_union_ty.errorUnionSet();
3059 const payload_ty = error_union_ty.errorUnionPayload();
3060 if (err_ty.errorSetIsEmpty()) {
3065 const mod = self.bin_file.options.module.?;
3066 const err_ty = error_union_ty.errorUnionSet(mod);
3067 const payload_ty = error_union_ty.errorUnionPayload(mod);
3068 if (err_ty.errorSetIsEmpty(mod)) {
30613069 return MCValue{ .immediate = 0 };
30623070 }
3063 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3071 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
30643072 return try error_union_bind.resolveToMcv(self);
30653073 }
30663074
3067 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));
3075 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, mod));
30683076 switch (try error_union_bind.resolveToMcv(self)) {
30693077 .register => {
30703078 var operand_reg: Register = undefined;
......@@ -3086,7 +3094,7 @@ fn errUnionErr(
30863094 );
30873095
30883096 const err_bit_offset = err_offset * 8;
3089 const err_bit_size = @intCast(u32, err_ty.abiSize(self.target.*)) * 8;
3097 const err_bit_size = @intCast(u32, err_ty.abiSize(mod)) * 8;
30903098
30913099 _ = try self.addInst(.{
30923100 .tag = .ubfx, // errors are unsigned integers
......@@ -3120,7 +3128,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
31203128 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
31213129 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
31223130 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
3123 const error_union_ty = self.air.typeOf(ty_op.operand);
3131 const error_union_ty = self.typeOf(ty_op.operand);
31243132
31253133 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);
31263134 };
......@@ -3134,16 +3142,17 @@ fn errUnionPayload(
31343142 error_union_ty: Type,
31353143 maybe_inst: ?Air.Inst.Index,
31363144) !MCValue {
3137 const err_ty = error_union_ty.errorUnionSet();
3138 const payload_ty = error_union_ty.errorUnionPayload();
3139 if (err_ty.errorSetIsEmpty()) {
3145 const mod = self.bin_file.options.module.?;
3146 const err_ty = error_union_ty.errorUnionSet(mod);
3147 const payload_ty = error_union_ty.errorUnionPayload(mod);
3148 if (err_ty.errorSetIsEmpty(mod)) {
31403149 return try error_union_bind.resolveToMcv(self);
31413150 }
3142 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3151 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
31433152 return MCValue.none;
31443153 }
31453154
3146 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));
3155 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
31473156 switch (try error_union_bind.resolveToMcv(self)) {
31483157 .register => {
31493158 var operand_reg: Register = undefined;
......@@ -3165,10 +3174,10 @@ fn errUnionPayload(
31653174 );
31663175
31673176 const payload_bit_offset = payload_offset * 8;
3168 const payload_bit_size = @intCast(u32, payload_ty.abiSize(self.target.*)) * 8;
3177 const payload_bit_size = @intCast(u32, payload_ty.abiSize(mod)) * 8;
31693178
31703179 _ = try self.addInst(.{
3171 .tag = if (payload_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx,
3180 .tag = if (payload_ty.isSignedInt(mod)) Mir.Inst.Tag.sbfx else .ubfx,
31723181 .data = .{
31733182 .rr_lsb_width = .{
31743183 // Set both registers to the X variant to get the full width
......@@ -3199,7 +3208,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
31993208 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
32003209 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
32013210 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
3202 const error_union_ty = self.air.typeOf(ty_op.operand);
3211 const error_union_ty = self.typeOf(ty_op.operand);
32033212
32043213 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);
32053214 };
......@@ -3245,6 +3254,7 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
32453254}
32463255
32473256fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3257 const mod = self.bin_file.options.module.?;
32483258 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
32493259
32503260 if (self.liveness.isUnused(inst)) {
......@@ -3252,12 +3262,12 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
32523262 }
32533263
32543264 const result: MCValue = result: {
3255 const payload_ty = self.air.typeOf(ty_op.operand);
3256 if (!payload_ty.hasRuntimeBits()) {
3265 const payload_ty = self.typeOf(ty_op.operand);
3266 if (!payload_ty.hasRuntimeBits(mod)) {
32573267 break :result MCValue{ .immediate = 1 };
32583268 }
32593269
3260 const optional_ty = self.air.typeOfIndex(inst);
3270 const optional_ty = self.typeOfIndex(inst);
32613271 const operand = try self.resolveInst(ty_op.operand);
32623272 const operand_lock: ?RegisterLock = switch (operand) {
32633273 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -3265,7 +3275,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
32653275 };
32663276 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
32673277
3268 if (optional_ty.isPtrLikeOptional()) {
3278 if (optional_ty.isPtrLikeOptional(mod)) {
32693279 // TODO should we check if we can reuse the operand?
32703280 const raw_reg = try self.register_manager.allocReg(inst, gp);
32713281 const reg = self.registerAlias(raw_reg, payload_ty);
......@@ -3273,9 +3283,9 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
32733283 break :result MCValue{ .register = reg };
32743284 }
32753285
3276 const optional_abi_size = @intCast(u32, optional_ty.abiSize(self.target.*));
3277 const optional_abi_align = optional_ty.abiAlignment(self.target.*);
3278 const offset = @intCast(u32, payload_ty.abiSize(self.target.*));
3286 const optional_abi_size = @intCast(u32, optional_ty.abiSize(mod));
3287 const optional_abi_align = optional_ty.abiAlignment(mod);
3288 const offset = @intCast(u32, payload_ty.abiSize(mod));
32793289
32803290 const stack_offset = try self.allocMem(optional_abi_size, optional_abi_align, inst);
32813291 try self.genSetStack(payload_ty, stack_offset, operand);
......@@ -3289,19 +3299,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
32893299
32903300/// T to E!T
32913301fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
3302 const mod = self.bin_file.options.module.?;
32923303 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
32933304 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
32943305 const error_union_ty = self.air.getRefType(ty_op.ty);
3295 const error_ty = error_union_ty.errorUnionSet();
3296 const payload_ty = error_union_ty.errorUnionPayload();
3306 const error_ty = error_union_ty.errorUnionSet(mod);
3307 const payload_ty = error_union_ty.errorUnionPayload(mod);
32973308 const operand = try self.resolveInst(ty_op.operand);
3298 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;
3309 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
32993310
3300 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
3301 const abi_align = error_union_ty.abiAlignment(self.target.*);
3311 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
3312 const abi_align = error_union_ty.abiAlignment(mod);
33023313 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
3303 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
3304 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
3314 const payload_off = errUnionPayloadOffset(payload_ty, mod);
3315 const err_off = errUnionErrorOffset(payload_ty, mod);
33053316 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);
33063317 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 });
33073318
......@@ -3314,17 +3325,18 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
33143325fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
33153326 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
33163327 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
3328 const mod = self.bin_file.options.module.?;
33173329 const error_union_ty = self.air.getRefType(ty_op.ty);
3318 const error_ty = error_union_ty.errorUnionSet();
3319 const payload_ty = error_union_ty.errorUnionPayload();
3330 const error_ty = error_union_ty.errorUnionSet(mod);
3331 const payload_ty = error_union_ty.errorUnionPayload(mod);
33203332 const operand = try self.resolveInst(ty_op.operand);
3321 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;
3333 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
33223334
3323 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
3324 const abi_align = error_union_ty.abiAlignment(self.target.*);
3335 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
3336 const abi_align = error_union_ty.abiAlignment(mod);
33253337 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
3326 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
3327 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
3338 const payload_off = errUnionPayloadOffset(payload_ty, mod);
3339 const err_off = errUnionErrorOffset(payload_ty, mod);
33283340 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);
33293341 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);
33303342
......@@ -3416,11 +3428,11 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
34163428}
34173429
34183430fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
3431 const mod = self.bin_file.options.module.?;
34193432 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3420 const slice_ty = self.air.typeOf(bin_op.lhs);
3421 const result: MCValue = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
3422 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3423 const ptr_ty = slice_ty.slicePtrFieldType(&buf);
3433 const slice_ty = self.typeOf(bin_op.lhs);
3434 const result: MCValue = if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
3435 const ptr_ty = slice_ty.slicePtrFieldType(mod);
34243436
34253437 const slice_mcv = try self.resolveInst(bin_op.lhs);
34263438 const base_mcv = slicePtr(slice_mcv);
......@@ -3440,8 +3452,9 @@ fn ptrElemVal(
34403452 ptr_ty: Type,
34413453 maybe_inst: ?Air.Inst.Index,
34423454) !MCValue {
3443 const elem_ty = ptr_ty.childType();
3444 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
3455 const mod = self.bin_file.options.module.?;
3456 const elem_ty = ptr_ty.childType(mod);
3457 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
34453458
34463459 // TODO optimize for elem_sizes of 1, 2, 4, 8
34473460 switch (elem_size) {
......@@ -3465,8 +3478,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
34653478 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
34663479 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
34673480
3468 const slice_ty = self.air.typeOf(extra.lhs);
3469 const index_ty = self.air.typeOf(extra.rhs);
3481 const slice_ty = self.typeOf(extra.lhs);
3482 const index_ty = self.typeOf(extra.rhs);
34703483
34713484 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);
34723485 break :result addr;
......@@ -3481,9 +3494,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
34813494}
34823495
34833496fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
3497 const mod = self.bin_file.options.module.?;
34843498 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3485 const ptr_ty = self.air.typeOf(bin_op.lhs);
3486 const result: MCValue = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
3499 const ptr_ty = self.typeOf(bin_op.lhs);
3500 const result: MCValue = if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
34873501 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
34883502 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
34893503
......@@ -3499,8 +3513,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
34993513 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };
35003514 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
35013515
3502 const ptr_ty = self.air.typeOf(extra.lhs);
3503 const index_ty = self.air.typeOf(extra.rhs);
3516 const ptr_ty = self.typeOf(extra.lhs);
3517 const index_ty = self.typeOf(extra.rhs);
35043518
35053519 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);
35063520 break :result addr;
......@@ -3597,8 +3611,9 @@ fn reuseOperand(
35973611}
35983612
35993613fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
3600 const elem_ty = ptr_ty.elemType();
3601 const elem_size = elem_ty.abiSize(self.target.*);
3614 const mod = self.bin_file.options.module.?;
3615 const elem_ty = ptr_ty.childType(mod);
3616 const elem_size = elem_ty.abiSize(mod);
36023617
36033618 switch (ptr) {
36043619 .none => unreachable,
......@@ -3753,14 +3768,14 @@ fn genInlineMemset(
37533768) !void {
37543769 const dst_reg = switch (dst) {
37553770 .register => |r| r,
3756 else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst),
3771 else => try self.copyToTmpRegister(Type.manyptr_u8, dst),
37573772 };
37583773 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
37593774 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
37603775
37613776 const val_reg = switch (val) {
37623777 .register => |r| r,
3763 else => try self.copyToTmpRegister(Type.initTag(.u8), val),
3778 else => try self.copyToTmpRegister(Type.u8, val),
37643779 };
37653780 const val_reg_lock = self.register_manager.lockReg(val_reg);
37663781 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);
......@@ -3844,15 +3859,16 @@ fn genInlineMemsetCode(
38443859}
38453860
38463861fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
3862 const mod = self.bin_file.options.module.?;
38473863 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3848 const elem_ty = self.air.typeOfIndex(inst);
3849 const elem_size = elem_ty.abiSize(self.target.*);
3864 const elem_ty = self.typeOfIndex(inst);
3865 const elem_size = elem_ty.abiSize(mod);
38503866 const result: MCValue = result: {
3851 if (!elem_ty.hasRuntimeBits())
3867 if (!elem_ty.hasRuntimeBits(mod))
38523868 break :result MCValue.none;
38533869
38543870 const ptr = try self.resolveInst(ty_op.operand);
3855 const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
3871 const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(mod);
38563872 if (self.liveness.isUnused(inst) and !is_volatile)
38573873 break :result MCValue.dead;
38583874
......@@ -3867,18 +3883,19 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
38673883 break :blk try self.allocRegOrMem(elem_ty, true, inst);
38683884 }
38693885 };
3870 try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand));
3886 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
38713887 break :result dst_mcv;
38723888 };
38733889 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
38743890}
38753891
38763892fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void {
3877 const abi_size = ty.abiSize(self.target.*);
3893 const mod = self.bin_file.options.module.?;
3894 const abi_size = ty.abiSize(mod);
38783895
38793896 const tag: Mir.Inst.Tag = switch (abi_size) {
3880 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_immediate else .ldrb_immediate,
3881 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_immediate else .ldrh_immediate,
3897 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_immediate else .ldrb_immediate,
3898 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_immediate else .ldrh_immediate,
38823899 4 => .ldr_immediate,
38833900 8 => .ldr_immediate,
38843901 3, 5, 6, 7 => return self.fail("TODO: genLdrRegister for more abi_sizes", .{}),
......@@ -3896,7 +3913,8 @@ fn genLdrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type
38963913}
38973914
38983915fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type) !void {
3899 const abi_size = ty.abiSize(self.target.*);
3916 const mod = self.bin_file.options.module.?;
3917 const abi_size = ty.abiSize(mod);
39003918
39013919 const tag: Mir.Inst.Tag = switch (abi_size) {
39023920 1 => .strb_immediate,
......@@ -3917,8 +3935,9 @@ fn genStrRegister(self: *Self, value_reg: Register, addr_reg: Register, ty: Type
39173935}
39183936
39193937fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
3938 const mod = self.bin_file.options.module.?;
39203939 log.debug("store: storing {} to {}", .{ value, ptr });
3921 const abi_size = value_ty.abiSize(self.target.*);
3940 const abi_size = value_ty.abiSize(mod);
39223941
39233942 switch (ptr) {
39243943 .none => unreachable,
......@@ -4046,8 +4065,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
40464065 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
40474066 const ptr = try self.resolveInst(bin_op.lhs);
40484067 const value = try self.resolveInst(bin_op.rhs);
4049 const ptr_ty = self.air.typeOf(bin_op.lhs);
4050 const value_ty = self.air.typeOf(bin_op.rhs);
4068 const ptr_ty = self.typeOf(bin_op.lhs);
4069 const value_ty = self.typeOf(bin_op.rhs);
40514070
40524071 try self.store(ptr, value, ptr_ty, value_ty);
40534072
......@@ -4069,10 +4088,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
40694088
40704089fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
40714090 return if (self.liveness.isUnused(inst)) .dead else result: {
4091 const mod = self.bin_file.options.module.?;
40724092 const mcv = try self.resolveInst(operand);
4073 const ptr_ty = self.air.typeOf(operand);
4074 const struct_ty = ptr_ty.childType();
4075 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
4093 const ptr_ty = self.typeOf(operand);
4094 const struct_ty = ptr_ty.childType(mod);
4095 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
40764096 switch (mcv) {
40774097 .ptr_stack_offset => |off| {
40784098 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
......@@ -4093,10 +4113,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
40934113 const operand = extra.struct_operand;
40944114 const index = extra.field_index;
40954115 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4116 const mod = self.bin_file.options.module.?;
40964117 const mcv = try self.resolveInst(operand);
4097 const struct_ty = self.air.typeOf(operand);
4098 const struct_field_ty = struct_ty.structFieldType(index);
4099 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
4118 const struct_ty = self.typeOf(operand);
4119 const struct_field_ty = struct_ty.structFieldType(index, mod);
4120 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
41004121
41014122 switch (mcv) {
41024123 .dead, .unreach => unreachable,
......@@ -4142,12 +4163,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
41424163}
41434164
41444165fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
4166 const mod = self.bin_file.options.module.?;
41454167 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
41464168 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
41474169 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
41484170 const field_ptr = try self.resolveInst(extra.field_ptr);
4149 const struct_ty = self.air.getRefType(ty_pl.ty).childType();
4150 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, self.target.*));
4171 const struct_ty = self.air.getRefType(ty_pl.ty).childType(mod);
4172 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, mod));
41514173 switch (field_ptr) {
41524174 .ptr_stack_offset => |off| {
41534175 break :result MCValue{ .ptr_stack_offset = off + struct_field_offset };
......@@ -4169,7 +4191,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
41694191 while (self.args[arg_index] == .none) arg_index += 1;
41704192 self.arg_index = arg_index + 1;
41714193
4172 const ty = self.air.typeOfIndex(inst);
4194 const ty = self.typeOfIndex(inst);
41734195 const tag = self.air.instructions.items(.tag)[inst];
41744196 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
41754197 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
......@@ -4222,11 +4244,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42224244 const callee = pl_op.operand;
42234245 const extra = self.air.extraData(Air.Call, pl_op.payload);
42244246 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
4225 const ty = self.air.typeOf(callee);
4247 const ty = self.typeOf(callee);
4248 const mod = self.bin_file.options.module.?;
42264249
4227 const fn_ty = switch (ty.zigTypeTag()) {
4250 const fn_ty = switch (ty.zigTypeTag(mod)) {
42284251 .Fn => ty,
4229 .Pointer => ty.childType(),
4252 .Pointer => ty.childType(mod),
42304253 else => unreachable,
42314254 };
42324255
......@@ -4245,18 +4268,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42454268
42464269 if (info.return_value == .stack_offset) {
42474270 log.debug("airCall: return by reference", .{});
4248 const ret_ty = fn_ty.fnReturnType();
4249 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4250 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
4271 const ret_ty = fn_ty.fnReturnType(mod);
4272 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
4273 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
42514274 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
42524275
42534276 const ret_ptr_reg = self.registerAlias(.x0, Type.usize);
42544277
4255 var ptr_ty_payload: Type.Payload.ElemType = .{
4256 .base = .{ .tag = .single_mut_pointer },
4257 .data = ret_ty,
4258 };
4259 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4278 const ptr_ty = try mod.singleMutPtrType(ret_ty);
42604279 try self.register_manager.getReg(ret_ptr_reg, null);
42614280 try self.genSetReg(ptr_ty, ret_ptr_reg, .{ .ptr_stack_offset = stack_offset });
42624281
......@@ -4268,7 +4287,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42684287
42694288 for (info.args, 0..) |mc_arg, arg_i| {
42704289 const arg = args[arg_i];
4271 const arg_ty = self.air.typeOf(arg);
4290 const arg_ty = self.typeOf(arg);
42724291 const arg_mcv = try self.resolveInst(args[arg_i]);
42734292
42744293 switch (mc_arg) {
......@@ -4289,21 +4308,18 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42894308
42904309 // Due to incremental compilation, how function calls are generated depends
42914310 // on linking.
4292 const mod = self.bin_file.options.module.?;
4293 if (self.air.value(callee)) |func_value| {
4294 if (func_value.castTag(.function)) |func_payload| {
4295 const func = func_payload.data;
4296
4311 if (try self.air.value(callee, mod)) |func_value| {
4312 if (func_value.getFunction(mod)) |func| {
42974313 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
42984314 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
42994315 const atom = elf_file.getAtom(atom_index);
43004316 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
43014317 const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));
4302 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
4318 try self.genSetReg(Type.usize, .x30, .{ .memory = got_addr });
43034319 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43044320 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
43054321 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
4306 try self.genSetReg(Type.initTag(.u64), .x30, .{
4322 try self.genSetReg(Type.u64, .x30, .{
43074323 .linker_load = .{
43084324 .type = .got,
43094325 .sym_index = sym_index,
......@@ -4312,7 +4328,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43124328 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
43134329 const atom = try coff_file.getOrCreateAtomForDecl(func.owner_decl);
43144330 const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
4315 try self.genSetReg(Type.initTag(.u64), .x30, .{
4331 try self.genSetReg(Type.u64, .x30, .{
43164332 .linker_load = .{
43174333 .type = .got,
43184334 .sym_index = sym_index,
......@@ -4326,17 +4342,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43264342 const got_addr = p9.bases.data;
43274343 const got_index = decl_block.got_index.?;
43284344 const fn_got_addr = got_addr + got_index * ptr_bytes;
4329 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
4345 try self.genSetReg(Type.usize, .x30, .{ .memory = fn_got_addr });
43304346 } else unreachable;
43314347
43324348 _ = try self.addInst(.{
43334349 .tag = .blr,
43344350 .data = .{ .reg = .x30 },
43354351 });
4336 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4337 const extern_fn = func_payload.data;
4338 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);
4339 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
4352 } else if (func_value.getExternFunc(mod)) |extern_func| {
4353 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
4354 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
43404355 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43414356 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
43424357 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
......@@ -4352,7 +4367,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43524367 });
43534368 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
43544369 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
4355 try self.genSetReg(Type.initTag(.u64), .x30, .{
4370 try self.genSetReg(Type.u64, .x30, .{
43564371 .linker_load = .{
43574372 .type = .import,
43584373 .sym_index = sym_index,
......@@ -4369,7 +4384,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43694384 return self.fail("TODO implement calling bitcasted functions", .{});
43704385 }
43714386 } else {
4372 assert(ty.zigTypeTag() == .Pointer);
4387 assert(ty.zigTypeTag(mod) == .Pointer);
43734388 const mcv = try self.resolveInst(callee);
43744389 try self.genSetReg(ty, .x30, mcv);
43754390
......@@ -4407,14 +4422,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
44074422}
44084423
44094424fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4425 const mod = self.bin_file.options.module.?;
44104426 const un_op = self.air.instructions.items(.data)[inst].un_op;
44114427 const operand = try self.resolveInst(un_op);
4412 const ret_ty = self.fn_type.fnReturnType();
4428 const ret_ty = self.fn_type.fnReturnType(mod);
44134429
44144430 switch (self.ret_mcv) {
44154431 .none => {},
44164432 .immediate => {
4417 assert(ret_ty.isError());
4433 assert(ret_ty.isError(mod));
44184434 },
44194435 .register => |reg| {
44204436 // Return result by value
......@@ -4425,11 +4441,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
44254441 //
44264442 // self.ret_mcv is an address to where this function
44274443 // should store its result into
4428 var ptr_ty_payload: Type.Payload.ElemType = .{
4429 .base = .{ .tag = .single_mut_pointer },
4430 .data = ret_ty,
4431 };
4432 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4444 const ptr_ty = try mod.singleMutPtrType(ret_ty);
44334445 try self.store(self.ret_mcv, operand, ptr_ty, ret_ty);
44344446 },
44354447 else => unreachable,
......@@ -4442,10 +4454,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
44424454}
44434455
44444456fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4457 const mod = self.bin_file.options.module.?;
44454458 const un_op = self.air.instructions.items(.data)[inst].un_op;
44464459 const ptr = try self.resolveInst(un_op);
4447 const ptr_ty = self.air.typeOf(un_op);
4448 const ret_ty = self.fn_type.fnReturnType();
4460 const ptr_ty = self.typeOf(un_op);
4461 const ret_ty = self.fn_type.fnReturnType(mod);
44494462
44504463 switch (self.ret_mcv) {
44514464 .none => {},
......@@ -4465,8 +4478,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44654478 // location.
44664479 const op_inst = Air.refToIndex(un_op).?;
44674480 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4468 const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4469 const abi_align = ret_ty.abiAlignment(self.target.*);
4481 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
4482 const abi_align = ret_ty.abiAlignment(mod);
44704483
44714484 const offset = try self.allocMem(abi_size, abi_align, null);
44724485
......@@ -4485,7 +4498,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44854498
44864499fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
44874500 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4488 const lhs_ty = self.air.typeOf(bin_op.lhs);
4501 const lhs_ty = self.typeOf(bin_op.lhs);
44894502
44904503 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
44914504 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);
......@@ -4501,29 +4514,28 @@ fn cmp(
45014514 lhs_ty: Type,
45024515 op: math.CompareOperator,
45034516) !MCValue {
4504 var int_buffer: Type.Payload.Bits = undefined;
4505 const int_ty = switch (lhs_ty.zigTypeTag()) {
4517 const mod = self.bin_file.options.module.?;
4518 const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
45064519 .Optional => blk: {
4507 var opt_buffer: Type.Payload.ElemType = undefined;
4508 const payload_ty = lhs_ty.optionalChild(&opt_buffer);
4509 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4510 break :blk Type.initTag(.u1);
4511 } else if (lhs_ty.isPtrLikeOptional()) {
4520 const payload_ty = lhs_ty.optionalChild(mod);
4521 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4522 break :blk Type.u1;
4523 } else if (lhs_ty.isPtrLikeOptional(mod)) {
45124524 break :blk Type.usize;
45134525 } else {
45144526 return self.fail("TODO ARM cmp non-pointer optionals", .{});
45154527 }
45164528 },
45174529 .Float => return self.fail("TODO ARM cmp floats", .{}),
4518 .Enum => lhs_ty.intTagType(&int_buffer),
4530 .Enum => lhs_ty.intTagType(mod),
45194531 .Int => lhs_ty,
4520 .Bool => Type.initTag(.u1),
4532 .Bool => Type.u1,
45214533 .Pointer => Type.usize,
4522 .ErrorSet => Type.initTag(.u16),
4534 .ErrorSet => Type.u16,
45234535 else => unreachable,
45244536 };
45254537
4526 const int_info = int_ty.intInfo(self.target.*);
4538 const int_info = int_ty.intInfo(mod);
45274539 if (int_info.bits <= 64) {
45284540 try self.spillCompareFlagsIfOccupied();
45294541
......@@ -4609,8 +4621,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
46094621}
46104622
46114623fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4612 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4613 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
4624 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4625 const mod = self.bin_file.options.module.?;
4626 const function = mod.funcPtr(ty_fn.func);
46144627 // TODO emit debug info for function change
46154628 _ = function;
46164629 return self.finishAir(inst, .dead, .{ .none, .none, .none });
......@@ -4625,7 +4638,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
46254638 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
46264639 const operand = pl_op.operand;
46274640 const tag = self.air.instructions.items(.tag)[inst];
4628 const ty = self.air.typeOf(operand);
4641 const ty = self.typeOf(operand);
46294642 const mcv = try self.resolveInst(operand);
46304643 const name = self.air.nullTerminatedString(pl_op.payload);
46314644
......@@ -4687,8 +4700,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
46874700 // whether it needs to be spilled in the branches
46884701 if (self.liveness.operandDies(inst, 0)) {
46894702 const op_int = @enumToInt(pl_op.operand);
4690 if (op_int >= Air.Inst.Ref.typed_value_map.len) {
4691 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
4703 if (op_int >= Air.ref_start_index) {
4704 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
46924705 self.processDeath(op_index);
46934706 }
46944707 }
......@@ -4777,7 +4790,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
47774790 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
47784791 // TODO make sure the destination stack offset / register does not already have something
47794792 // going on there.
4780 try self.setRegOrMem(self.air.typeOfIndex(else_key), canon_mcv, else_value);
4793 try self.setRegOrMem(self.typeOfIndex(else_key), canon_mcv, else_value);
47814794 // TODO track the new register / stack allocation
47824795 }
47834796 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count());
......@@ -4804,7 +4817,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
48044817 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
48054818 // TODO make sure the destination stack offset / register does not already have something
48064819 // going on there.
4807 try self.setRegOrMem(self.air.typeOfIndex(then_key), parent_mcv, then_value);
4820 try self.setRegOrMem(self.typeOfIndex(then_key), parent_mcv, then_value);
48084821 // TODO track the new register / stack allocation
48094822 }
48104823
......@@ -4819,13 +4832,13 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
48194832}
48204833
48214834fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue {
4822 const sentinel: struct { ty: Type, bind: ReadArg.Bind } = if (!operand_ty.isPtrLikeOptional()) blk: {
4823 var buf: Type.Payload.ElemType = undefined;
4824 const payload_ty = operand_ty.optionalChild(&buf);
4825 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
4835 const mod = self.bin_file.options.module.?;
4836 const sentinel: struct { ty: Type, bind: ReadArg.Bind } = if (!operand_ty.isPtrLikeOptional(mod)) blk: {
4837 const payload_ty = operand_ty.optionalChild(mod);
4838 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
48264839 break :blk .{ .ty = operand_ty, .bind = operand_bind };
48274840
4828 const offset = @intCast(u32, payload_ty.abiSize(self.target.*));
4841 const offset = @intCast(u32, payload_ty.abiSize(mod));
48294842 const operand_mcv = try operand_bind.resolveToMcv(self);
48304843 const new_mcv: MCValue = switch (operand_mcv) {
48314844 .register => |source_reg| new: {
......@@ -4838,7 +4851,7 @@ fn isNull(self: *Self, operand_bind: ReadArg.Bind, operand_ty: Type) !MCValue {
48384851 try self.genSetReg(payload_ty, dest_reg, operand_mcv);
48394852 } else {
48404853 _ = try self.addInst(.{
4841 .tag = if (payload_ty.isSignedInt())
4854 .tag = if (payload_ty.isSignedInt(mod))
48424855 Mir.Inst.Tag.asr_immediate
48434856 else
48444857 Mir.Inst.Tag.lsr_immediate,
......@@ -4875,9 +4888,10 @@ fn isErr(
48754888 error_union_bind: ReadArg.Bind,
48764889 error_union_ty: Type,
48774890) !MCValue {
4878 const error_type = error_union_ty.errorUnionSet();
4891 const mod = self.bin_file.options.module.?;
4892 const error_type = error_union_ty.errorUnionSet(mod);
48794893
4880 if (error_type.errorSetIsEmpty()) {
4894 if (error_type.errorSetIsEmpty(mod)) {
48814895 return MCValue{ .immediate = 0 }; // always false
48824896 }
48834897
......@@ -4908,7 +4922,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
49084922 const un_op = self.air.instructions.items(.data)[inst].un_op;
49094923 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49104924 const operand = try self.resolveInst(un_op);
4911 const operand_ty = self.air.typeOf(un_op);
4925 const operand_ty = self.typeOf(un_op);
49124926
49134927 break :result try self.isNull(.{ .mcv = operand }, operand_ty);
49144928 };
......@@ -4916,11 +4930,12 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
49164930}
49174931
49184932fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4933 const mod = self.bin_file.options.module.?;
49194934 const un_op = self.air.instructions.items(.data)[inst].un_op;
49204935 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49214936 const operand_ptr = try self.resolveInst(un_op);
4922 const ptr_ty = self.air.typeOf(un_op);
4923 const elem_ty = ptr_ty.elemType();
4937 const ptr_ty = self.typeOf(un_op);
4938 const elem_ty = ptr_ty.childType(mod);
49244939
49254940 const operand = try self.allocRegOrMem(elem_ty, true, null);
49264941 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4934,7 +4949,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
49344949 const un_op = self.air.instructions.items(.data)[inst].un_op;
49354950 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49364951 const operand = try self.resolveInst(un_op);
4937 const operand_ty = self.air.typeOf(un_op);
4952 const operand_ty = self.typeOf(un_op);
49384953
49394954 break :result try self.isNonNull(.{ .mcv = operand }, operand_ty);
49404955 };
......@@ -4942,11 +4957,12 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
49424957}
49434958
49444959fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4960 const mod = self.bin_file.options.module.?;
49454961 const un_op = self.air.instructions.items(.data)[inst].un_op;
49464962 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49474963 const operand_ptr = try self.resolveInst(un_op);
4948 const ptr_ty = self.air.typeOf(un_op);
4949 const elem_ty = ptr_ty.elemType();
4964 const ptr_ty = self.typeOf(un_op);
4965 const elem_ty = ptr_ty.childType(mod);
49504966
49514967 const operand = try self.allocRegOrMem(elem_ty, true, null);
49524968 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4960,7 +4976,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
49604976 const un_op = self.air.instructions.items(.data)[inst].un_op;
49614977 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49624978 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };
4963 const error_union_ty = self.air.typeOf(un_op);
4979 const error_union_ty = self.typeOf(un_op);
49644980
49654981 break :result try self.isErr(error_union_bind, error_union_ty);
49664982 };
......@@ -4968,11 +4984,12 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
49684984}
49694985
49704986fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4987 const mod = self.bin_file.options.module.?;
49714988 const un_op = self.air.instructions.items(.data)[inst].un_op;
49724989 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49734990 const operand_ptr = try self.resolveInst(un_op);
4974 const ptr_ty = self.air.typeOf(un_op);
4975 const elem_ty = ptr_ty.elemType();
4991 const ptr_ty = self.typeOf(un_op);
4992 const elem_ty = ptr_ty.childType(mod);
49764993
49774994 const operand = try self.allocRegOrMem(elem_ty, true, null);
49784995 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4986,7 +5003,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
49865003 const un_op = self.air.instructions.items(.data)[inst].un_op;
49875004 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49885005 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };
4989 const error_union_ty = self.air.typeOf(un_op);
5006 const error_union_ty = self.typeOf(un_op);
49905007
49915008 break :result try self.isNonErr(error_union_bind, error_union_ty);
49925009 };
......@@ -4994,11 +5011,12 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
49945011}
49955012
49965013fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
5014 const mod = self.bin_file.options.module.?;
49975015 const un_op = self.air.instructions.items(.data)[inst].un_op;
49985016 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49995017 const operand_ptr = try self.resolveInst(un_op);
5000 const ptr_ty = self.air.typeOf(un_op);
5001 const elem_ty = ptr_ty.elemType();
5018 const ptr_ty = self.typeOf(un_op);
5019 const elem_ty = ptr_ty.childType(mod);
50025020
50035021 const operand = try self.allocRegOrMem(elem_ty, true, null);
50045022 try self.load(operand, operand_ptr, ptr_ty);
......@@ -5065,7 +5083,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
50655083
50665084fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
50675085 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
5068 const condition_ty = self.air.typeOf(pl_op.operand);
5086 const condition_ty = self.typeOf(pl_op.operand);
50695087 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
50705088 const liveness = try self.liveness.getSwitchBr(
50715089 self.gpa,
......@@ -5210,9 +5228,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
52105228}
52115229
52125230fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5231 const mod = self.bin_file.options.module.?;
52135232 const block_data = self.blocks.getPtr(block).?;
52145233
5215 if (self.air.typeOf(operand).hasRuntimeBits()) {
5234 if (self.typeOf(operand).hasRuntimeBits(mod)) {
52165235 const operand_mcv = try self.resolveInst(operand);
52175236 const block_mcv = block_data.mcv;
52185237 if (block_mcv == .none) {
......@@ -5220,14 +5239,14 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
52205239 .none, .dead, .unreach => unreachable,
52215240 .register, .stack_offset, .memory => operand_mcv,
52225241 .immediate, .stack_argument_offset, .compare_flags => blk: {
5223 const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block);
5224 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
5242 const new_mcv = try self.allocRegOrMem(self.typeOfIndex(block), true, block);
5243 try self.setRegOrMem(self.typeOfIndex(block), new_mcv, operand_mcv);
52255244 break :blk new_mcv;
52265245 },
52275246 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
52285247 };
52295248 } else {
5230 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
5249 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
52315250 }
52325251 }
52335252 return self.brVoid(block);
......@@ -5293,7 +5312,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
52935312
52945313 const arg_mcv = try self.resolveInst(input);
52955314 try self.register_manager.getReg(reg, null);
5296 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
5315 try self.genSetReg(self.typeOf(input), reg, arg_mcv);
52975316 }
52985317
52995318 {
......@@ -5386,7 +5405,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
53865405}
53875406
53885407fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
5389 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5408 const mod = self.bin_file.options.module.?;
5409 const abi_size = @intCast(u32, ty.abiSize(mod));
53905410 switch (mcv) {
53915411 .dead => unreachable,
53925412 .unreach, .none => return, // Nothing to do.
......@@ -5441,11 +5461,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54415461 const reg_lock = self.register_manager.lockReg(rwo.reg);
54425462 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
54435463
5444 const wrapped_ty = ty.structFieldType(0);
5464 const wrapped_ty = ty.structFieldType(0, mod);
54455465 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });
54465466
5447 const overflow_bit_ty = ty.structFieldType(1);
5448 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
5467 const overflow_bit_ty = ty.structFieldType(1, mod);
5468 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
54495469 const raw_cond_reg = try self.register_manager.allocReg(null, gp);
54505470 const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty);
54515471
......@@ -5478,11 +5498,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54785498 const reg = try self.copyToTmpRegister(ty, mcv);
54795499 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
54805500 } else {
5481 var ptr_ty_payload: Type.Payload.ElemType = .{
5482 .base = .{ .tag = .single_mut_pointer },
5483 .data = ty,
5484 };
5485 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
5501 const ptr_ty = try mod.singleMutPtrType(ty);
54865502
54875503 // TODO call extern memcpy
54885504 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);
......@@ -5559,6 +5575,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
55595575}
55605576
55615577fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
5578 const mod = self.bin_file.options.module.?;
55625579 switch (mcv) {
55635580 .dead => unreachable,
55645581 .unreach, .none => return, // Nothing to do.
......@@ -5669,13 +5686,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56695686 try self.genLdrRegister(reg, reg.toX(), ty);
56705687 },
56715688 .stack_offset => |off| {
5672 const abi_size = ty.abiSize(self.target.*);
5689 const abi_size = ty.abiSize(mod);
56735690
56745691 switch (abi_size) {
56755692 1, 2, 4, 8 => {
56765693 const tag: Mir.Inst.Tag = switch (abi_size) {
5677 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack else .ldrb_stack,
5678 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack else .ldrh_stack,
5694 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack else .ldrb_stack,
5695 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack else .ldrh_stack,
56795696 4, 8 => .ldr_stack,
56805697 else => unreachable, // unexpected abi size
56815698 };
......@@ -5693,13 +5710,13 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56935710 }
56945711 },
56955712 .stack_argument_offset => |off| {
5696 const abi_size = ty.abiSize(self.target.*);
5713 const abi_size = ty.abiSize(mod);
56975714
56985715 switch (abi_size) {
56995716 1, 2, 4, 8 => {
57005717 const tag: Mir.Inst.Tag = switch (abi_size) {
5701 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,
5702 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
5718 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,
5719 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
57035720 4, 8 => .ldr_stack_argument,
57045721 else => unreachable, // unexpected abi size
57055722 };
......@@ -5720,7 +5737,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
57205737}
57215738
57225739fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
5723 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5740 const mod = self.bin_file.options.module.?;
5741 const abi_size = @intCast(u32, ty.abiSize(mod));
57245742 switch (mcv) {
57255743 .dead => unreachable,
57265744 .none, .unreach => return,
......@@ -5728,7 +5746,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
57285746 if (!self.wantSafety())
57295747 return; // The already existing value will do just fine.
57305748 // TODO Upgrade this to a memset call when we have that available.
5731 switch (ty.abiSize(self.target.*)) {
5749 switch (ty.abiSize(mod)) {
57325750 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
57335751 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
57345752 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
......@@ -5798,11 +5816,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
57985816 const reg = try self.copyToTmpRegister(ty, mcv);
57995817 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
58005818 } else {
5801 var ptr_ty_payload: Type.Payload.ElemType = .{
5802 .base = .{ .tag = .single_mut_pointer },
5803 .data = ty,
5804 };
5805 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
5819 const ptr_ty = try mod.singleMutPtrType(ty);
58065820
58075821 // TODO call extern memcpy
58085822 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);
......@@ -5913,7 +5927,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
59135927 };
59145928 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
59155929
5916 const dest_ty = self.air.typeOfIndex(inst);
5930 const dest_ty = self.typeOfIndex(inst);
59175931 const dest = try self.allocRegOrMem(dest_ty, true, inst);
59185932 try self.setRegOrMem(dest_ty, dest, operand);
59195933 break :result dest;
......@@ -5922,19 +5936,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
59225936}
59235937
59245938fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
5939 const mod = self.bin_file.options.module.?;
59255940 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
59265941 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
5927 const ptr_ty = self.air.typeOf(ty_op.operand);
5942 const ptr_ty = self.typeOf(ty_op.operand);
59285943 const ptr = try self.resolveInst(ty_op.operand);
5929 const array_ty = ptr_ty.childType();
5930 const array_len = @intCast(u32, array_ty.arrayLen());
5944 const array_ty = ptr_ty.childType(mod);
5945 const array_len = @intCast(u32, array_ty.arrayLen(mod));
59315946
59325947 const ptr_bits = self.target.ptrBitWidth();
59335948 const ptr_bytes = @divExact(ptr_bits, 8);
59345949
59355950 const stack_offset = try self.allocMem(ptr_bytes * 2, ptr_bytes * 2, inst);
59365951 try self.genSetStack(ptr_ty, stack_offset, ptr);
5937 try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len });
5952 try self.genSetStack(Type.usize, stack_offset - ptr_bytes, .{ .immediate = array_len });
59385953 break :result MCValue{ .stack_offset = stack_offset };
59395954 };
59405955 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -6044,8 +6059,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
60446059}
60456060
60466061fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
6047 const vector_ty = self.air.typeOfIndex(inst);
6048 const len = vector_ty.vectorLen();
6062 const mod = self.bin_file.options.module.?;
6063 const vector_ty = self.typeOfIndex(inst);
6064 const len = vector_ty.vectorLen(mod);
60496065 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
60506066 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
60516067 const result: MCValue = res: {
......@@ -6087,14 +6103,15 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
60876103}
60886104
60896105fn airTry(self: *Self, inst: Air.Inst.Index) !void {
6106 const mod = self.bin_file.options.module.?;
60906107 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
60916108 const extra = self.air.extraData(Air.Try, pl_op.payload);
60926109 const body = self.air.extra[extra.end..][0..extra.data.body_len];
60936110 const result: MCValue = result: {
60946111 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };
6095 const error_union_ty = self.air.typeOf(pl_op.operand);
6096 const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
6097 const error_union_align = error_union_ty.abiAlignment(self.target.*);
6112 const error_union_ty = self.typeOf(pl_op.operand);
6113 const error_union_size = @intCast(u32, error_union_ty.abiSize(mod));
6114 const error_union_align = error_union_ty.abiAlignment(mod);
60986115
60996116 // The error union will die in the body. However, we need the
61006117 // error union after the body in order to extract the payload
......@@ -6123,37 +6140,32 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
61236140}
61246141
61256142fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6126 // First section of indexes correspond to a set number of constant values.
6127 const ref_int = @enumToInt(inst);
6128 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
6129 const tv = Air.Inst.Ref.typed_value_map[ref_int];
6130 if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) {
6131 return MCValue{ .none = {} };
6132 }
6133 return self.genTypedValue(tv);
6134 }
6143 const mod = self.bin_file.options.module.?;
61356144
61366145 // If the type has no codegen bits, no need to store it.
6137 const inst_ty = self.air.typeOf(inst);
6138 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())
6146 const inst_ty = self.typeOf(inst);
6147 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))
61396148 return MCValue{ .none = {} };
61406149
6141 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
6150 const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
6151 .ty = inst_ty,
6152 .val = (try self.air.value(inst, mod)).?,
6153 });
6154
61426155 switch (self.air.instructions.items(.tag)[inst_index]) {
6143 .constant => {
6156 .interned => {
61446157 // Constants have static lifetimes, so they are always memoized in the outer most table.
61456158 const branch = &self.branch_stack.items[0];
61466159 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
61476160 if (!gop.found_existing) {
6148 const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;
6161 const interned = self.air.instructions.items(.data)[inst_index].interned;
61496162 gop.value_ptr.* = try self.genTypedValue(.{
61506163 .ty = inst_ty,
6151 .val = self.air.values[ty_pl.payload],
6164 .val = interned.toValue(),
61526165 });
61536166 }
61546167 return gop.value_ptr.*;
61556168 },
6156 .const_ty => unreachable,
61576169 else => return self.getResolvedInstValue(inst_index),
61586170 }
61596171}
......@@ -6208,12 +6220,11 @@ const CallMCValues = struct {
62086220
62096221/// Caller must call `CallMCValues.deinit`.
62106222fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6211 const cc = fn_ty.fnCallingConvention();
6212 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
6213 defer self.gpa.free(param_types);
6214 fn_ty.fnParamTypes(param_types);
6223 const mod = self.bin_file.options.module.?;
6224 const fn_info = mod.typeToFunc(fn_ty).?;
6225 const cc = fn_info.cc;
62156226 var result: CallMCValues = .{
6216 .args = try self.gpa.alloc(MCValue, param_types.len),
6227 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
62176228 // These undefined values must be populated before returning from this function.
62186229 .return_value = undefined,
62196230 .stack_byte_count = undefined,
......@@ -6221,7 +6232,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62216232 };
62226233 errdefer self.gpa.free(result.args);
62236234
6224 const ret_ty = fn_ty.fnReturnType();
6235 const ret_ty = fn_ty.fnReturnType(mod);
62256236
62266237 switch (cc) {
62276238 .Naked => {
......@@ -6236,14 +6247,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62366247 var ncrn: usize = 0; // Next Core Register Number
62376248 var nsaa: u32 = 0; // Next stacked argument address
62386249
6239 if (ret_ty.zigTypeTag() == .NoReturn) {
6250 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
62406251 result.return_value = .{ .unreach = {} };
6241 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
6252 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) {
62426253 result.return_value = .{ .none = {} };
62436254 } else {
6244 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
6255 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
62456256 if (ret_ty_size == 0) {
6246 assert(ret_ty.isError());
6257 assert(ret_ty.isError(mod));
62476258 result.return_value = .{ .immediate = 0 };
62486259 } else if (ret_ty_size <= 8) {
62496260 result.return_value = .{ .register = self.registerAlias(c_abi_int_return_regs[0], ret_ty) };
......@@ -6252,8 +6263,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62526263 }
62536264 }
62546265
6255 for (param_types, 0..) |ty, i| {
6256 const param_size = @intCast(u32, ty.abiSize(self.target.*));
6266 for (fn_info.param_types, 0..) |ty, i| {
6267 const param_size = @intCast(u32, ty.toType().abiSize(mod));
62576268 if (param_size == 0) {
62586269 result.args[i] = .{ .none = {} };
62596270 continue;
......@@ -6261,14 +6272,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62616272
62626273 // We round up NCRN only for non-Apple platforms which allow the 16-byte aligned
62636274 // values to spread across odd-numbered registers.
6264 if (ty.abiAlignment(self.target.*) == 16 and !self.target.isDarwin()) {
6275 if (ty.toType().abiAlignment(mod) == 16 and !self.target.isDarwin()) {
62656276 // Round up NCRN to the next even number
62666277 ncrn += ncrn % 2;
62676278 }
62686279
62696280 if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) {
62706281 if (param_size <= 8) {
6271 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty) };
6282 result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty.toType()) };
62726283 ncrn += 1;
62736284 } else {
62746285 return self.fail("TODO MCValues with multiple registers", .{});
......@@ -6279,7 +6290,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62796290 ncrn = 8;
62806291 // TODO Apple allows the arguments on the stack to be non-8-byte aligned provided
62816292 // that the entire stack space consumed by the arguments is 8-byte aligned.
6282 if (ty.abiAlignment(self.target.*) == 8) {
6293 if (ty.toType().abiAlignment(mod) == 8) {
62836294 if (nsaa % 8 != 0) {
62846295 nsaa += 8 - (nsaa % 8);
62856296 }
......@@ -6294,14 +6305,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62946305 result.stack_align = 16;
62956306 },
62966307 .Unspecified => {
6297 if (ret_ty.zigTypeTag() == .NoReturn) {
6308 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
62986309 result.return_value = .{ .unreach = {} };
6299 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
6310 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) {
63006311 result.return_value = .{ .none = {} };
63016312 } else {
6302 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
6313 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
63036314 if (ret_ty_size == 0) {
6304 assert(ret_ty.isError());
6315 assert(ret_ty.isError(mod));
63056316 result.return_value = .{ .immediate = 0 };
63066317 } else if (ret_ty_size <= 8) {
63076318 result.return_value = .{ .register = self.registerAlias(.x0, ret_ty) };
......@@ -6317,10 +6328,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
63176328
63186329 var stack_offset: u32 = 0;
63196330
6320 for (param_types, 0..) |ty, i| {
6321 if (ty.abiSize(self.target.*) > 0) {
6322 const param_size = @intCast(u32, ty.abiSize(self.target.*));
6323 const param_alignment = ty.abiAlignment(self.target.*);
6331 for (fn_info.param_types, 0..) |ty, i| {
6332 if (ty.toType().abiSize(mod) > 0) {
6333 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6334 const param_alignment = ty.toType().abiAlignment(mod);
63246335
63256336 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
63266337 result.args[i] = .{ .stack_argument_offset = stack_offset };
......@@ -6371,7 +6382,8 @@ fn parseRegName(name: []const u8) ?Register {
63716382}
63726383
63736384fn registerAlias(self: *Self, reg: Register, ty: Type) Register {
6374 const abi_size = ty.abiSize(self.target.*);
6385 const mod = self.bin_file.options.module.?;
6386 const abi_size = ty.abiSize(mod);
63756387
63766388 switch (reg.class()) {
63776389 .general_purpose => {
......@@ -6397,3 +6409,13 @@ fn registerAlias(self: *Self, reg: Register, ty: Type) Register {
63976409 },
63986410 }
63996411}
6412
6413fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
6414 const mod = self.bin_file.options.module.?;
6415 return self.air.typeOf(inst, &mod.intern_pool);
6416}
6417
6418fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
6419 const mod = self.bin_file.options.module.?;
6420 return self.air.typeOfIndex(inst, &mod.intern_pool);
6421}
src/arch/aarch64/abi.zig+28-26
......@@ -4,6 +4,7 @@ const bits = @import("bits.zig");
44const Register = bits.Register;
55const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
66const Type = @import("../../type.zig").Type;
7const Module = @import("../../Module.zig");
78
89pub const Class = union(enum) {
910 memory,
......@@ -14,44 +15,44 @@ pub const Class = union(enum) {
1415};
1516
1617/// For `float_array` the second element will be the amount of floats.
17pub fn classifyType(ty: Type, target: std.Target) Class {
18 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime());
18pub fn classifyType(ty: Type, mod: *Module) Class {
19 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1920
2021 var maybe_float_bits: ?u16 = null;
21 switch (ty.zigTypeTag()) {
22 switch (ty.zigTypeTag(mod)) {
2223 .Struct => {
23 if (ty.containerLayout() == .Packed) return .byval;
24 const float_count = countFloats(ty, target, &maybe_float_bits);
24 if (ty.containerLayout(mod) == .Packed) return .byval;
25 const float_count = countFloats(ty, mod, &maybe_float_bits);
2526 if (float_count <= sret_float_count) return .{ .float_array = float_count };
2627
27 const bit_size = ty.bitSize(target);
28 const bit_size = ty.bitSize(mod);
2829 if (bit_size > 128) return .memory;
2930 if (bit_size > 64) return .double_integer;
3031 return .integer;
3132 },
3233 .Union => {
33 if (ty.containerLayout() == .Packed) return .byval;
34 const float_count = countFloats(ty, target, &maybe_float_bits);
34 if (ty.containerLayout(mod) == .Packed) return .byval;
35 const float_count = countFloats(ty, mod, &maybe_float_bits);
3536 if (float_count <= sret_float_count) return .{ .float_array = float_count };
3637
37 const bit_size = ty.bitSize(target);
38 const bit_size = ty.bitSize(mod);
3839 if (bit_size > 128) return .memory;
3940 if (bit_size > 64) return .double_integer;
4041 return .integer;
4142 },
4243 .Int, .Enum, .ErrorSet, .Float, .Bool => return .byval,
4344 .Vector => {
44 const bit_size = ty.bitSize(target);
45 const bit_size = ty.bitSize(mod);
4546 // TODO is this controlled by a cpu feature?
4647 if (bit_size > 128) return .memory;
4748 return .byval;
4849 },
4950 .Optional => {
50 std.debug.assert(ty.isPtrLikeOptional());
51 std.debug.assert(ty.isPtrLikeOptional(mod));
5152 return .byval;
5253 },
5354 .Pointer => {
54 std.debug.assert(!ty.isSlice());
55 std.debug.assert(!ty.isSlice(mod));
5556 return .byval;
5657 },
5758 .ErrorUnion,
......@@ -73,14 +74,15 @@ pub fn classifyType(ty: Type, target: std.Target) Class {
7374}
7475
7576const sret_float_count = 4;
76fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
77fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 {
78 const target = mod.getTarget();
7779 const invalid = std.math.maxInt(u8);
78 switch (ty.zigTypeTag()) {
80 switch (ty.zigTypeTag(mod)) {
7981 .Union => {
80 const fields = ty.unionFields();
82 const fields = ty.unionFields(mod);
8183 var max_count: u8 = 0;
8284 for (fields.values()) |field| {
83 const field_count = countFloats(field.ty, target, maybe_float_bits);
85 const field_count = countFloats(field.ty, mod, maybe_float_bits);
8486 if (field_count == invalid) return invalid;
8587 if (field_count > max_count) max_count = field_count;
8688 if (max_count > sret_float_count) return invalid;
......@@ -88,12 +90,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
8890 return max_count;
8991 },
9092 .Struct => {
91 const fields_len = ty.structFieldCount();
93 const fields_len = ty.structFieldCount(mod);
9294 var count: u8 = 0;
9395 var i: u32 = 0;
9496 while (i < fields_len) : (i += 1) {
95 const field_ty = ty.structFieldType(i);
96 const field_count = countFloats(field_ty, target, maybe_float_bits);
97 const field_ty = ty.structFieldType(i, mod);
98 const field_count = countFloats(field_ty, mod, maybe_float_bits);
9799 if (field_count == invalid) return invalid;
98100 count += field_count;
99101 if (count > sret_float_count) return invalid;
......@@ -113,21 +115,21 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u8 {
113115 }
114116}
115117
116pub fn getFloatArrayType(ty: Type) ?Type {
117 switch (ty.zigTypeTag()) {
118pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type {
119 switch (ty.zigTypeTag(mod)) {
118120 .Union => {
119 const fields = ty.unionFields();
121 const fields = ty.unionFields(mod);
120122 for (fields.values()) |field| {
121 if (getFloatArrayType(field.ty)) |some| return some;
123 if (getFloatArrayType(field.ty, mod)) |some| return some;
122124 }
123125 return null;
124126 },
125127 .Struct => {
126 const fields_len = ty.structFieldCount();
128 const fields_len = ty.structFieldCount(mod);
127129 var i: u32 = 0;
128130 while (i < fields_len) : (i += 1) {
129 const field_ty = ty.structFieldType(i);
130 if (getFloatArrayType(field_ty)) |some| return some;
131 const field_ty = ty.structFieldType(i, mod);
132 if (getFloatArrayType(field_ty, mod)) |some| return some;
131133 }
132134 return null;
133135 },
src/arch/arm/CodeGen.zig+365-342
......@@ -334,7 +334,7 @@ const Self = @This();
334334pub fn generate(
335335 bin_file: *link.File,
336336 src_loc: Module.SrcLoc,
337 module_fn: *Module.Fn,
337 module_fn_index: Module.Fn.Index,
338338 air: Air,
339339 liveness: Liveness,
340340 code: *std.ArrayList(u8),
......@@ -345,6 +345,7 @@ pub fn generate(
345345 }
346346
347347 const mod = bin_file.options.module.?;
348 const module_fn = mod.funcPtr(module_fn_index);
348349 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
349350 assert(fn_owner_decl.has_tv);
350351 const fn_type = fn_owner_decl.ty;
......@@ -477,7 +478,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
477478}
478479
479480fn gen(self: *Self) !void {
480 const cc = self.fn_type.fnCallingConvention();
481 const mod = self.bin_file.options.module.?;
482 const cc = self.fn_type.fnCallingConvention(mod);
481483 if (cc != .Naked) {
482484 // push {fp, lr}
483485 const push_reloc = try self.addNop();
......@@ -518,10 +520,10 @@ fn gen(self: *Self) !void {
518520 const inst = self.air.getMainBody()[arg_index];
519521 assert(self.air.instructions.items(.tag)[inst] == .arg);
520522
521 const ty = self.air.typeOfIndex(inst);
523 const ty = self.typeOfIndex(inst);
522524
523 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
524 const abi_align = ty.abiAlignment(self.target.*);
525 const abi_size = @intCast(u32, ty.abiSize(mod));
526 const abi_align = ty.abiAlignment(mod);
525527 const stack_offset = try self.allocMem(abi_size, abi_align, inst);
526528 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
527529
......@@ -636,13 +638,14 @@ fn gen(self: *Self) !void {
636638}
637639
638640fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
641 const mod = self.bin_file.options.module.?;
642 const ip = &mod.intern_pool;
639643 const air_tags = self.air.instructions.items(.tag);
640644
641645 for (body) |inst| {
642646 // TODO: remove now-redundant isUnused calls from AIR handler functions
643 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
647 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
644648 continue;
645 }
646649
647650 const old_air_bookkeeping = self.air_bookkeeping;
648651 try self.ensureProcessDeathCapacity(Liveness.bpi);
......@@ -826,8 +829,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
826829 .ptr_elem_val => try self.airPtrElemVal(inst),
827830 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
828831
829 .constant => unreachable, // excluded from function bodies
830 .const_ty => unreachable, // excluded from function bodies
832 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
831833 .unreach => self.finishAirBookkeeping(),
832834
833835 .optional_payload => try self.airOptionalPayload(inst),
......@@ -900,8 +902,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
900902
901903/// Asserts there is already capacity to insert into top branch inst_table.
902904fn processDeath(self: *Self, inst: Air.Inst.Index) void {
903 const air_tags = self.air.instructions.items(.tag);
904 if (air_tags[inst] == .constant) return; // Constants are immortal.
905 assert(self.air.instructions.items(.tag)[inst] != .interned);
905906 // When editing this function, note that the logic must synchronize with `reuseOperand`.
906907 const prev_value = self.getResolvedInstValue(inst);
907908 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -937,8 +938,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
937938 tomb_bits >>= 1;
938939 if (!dies) continue;
939940 const op_int = @enumToInt(op);
940 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;
941 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
941 if (op_int < Air.ref_start_index) continue;
942 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
942943 self.processDeath(op_index);
943944 }
944945 const is_used = @truncate(u1, tomb_bits) == 0;
......@@ -1006,9 +1007,10 @@ fn allocMem(
10061007
10071008/// Use a pointer instruction as the basis for allocating stack memory.
10081009fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
1009 const elem_ty = self.air.typeOfIndex(inst).elemType();
1010 const mod = self.bin_file.options.module.?;
1011 const elem_ty = self.typeOfIndex(inst).childType(mod);
10101012
1011 if (!elem_ty.hasRuntimeBits()) {
1013 if (!elem_ty.hasRuntimeBits(mod)) {
10121014 // As this stack item will never be dereferenced at runtime,
10131015 // return the stack offset 0. Stack offset 0 will be where all
10141016 // zero-sized stack allocations live as non-zero-sized
......@@ -1016,22 +1018,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
10161018 return @as(u32, 0);
10171019 }
10181020
1019 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
1020 const mod = self.bin_file.options.module.?;
1021 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
10211022 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
10221023 };
10231024 // TODO swap this for inst.ty.ptrAlign
1024 const abi_align = elem_ty.abiAlignment(self.target.*);
1025 const abi_align = elem_ty.abiAlignment(mod);
10251026
10261027 return self.allocMem(abi_size, abi_align, inst);
10271028}
10281029
10291030fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst.Index) !MCValue {
1030 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
1031 const mod = self.bin_file.options.module.?;
1031 const mod = self.bin_file.options.module.?;
1032 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
10321033 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
10331034 };
1034 const abi_align = elem_ty.abiAlignment(self.target.*);
1035 const abi_align = elem_ty.abiAlignment(mod);
10351036
10361037 if (reg_ok) {
10371038 // Make sure the type can fit in a register before we try to allocate one.
......@@ -1049,7 +1050,7 @@ fn allocRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool, maybe_inst: ?Air.Inst
10491050}
10501051
10511052pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void {
1052 const stack_mcv = try self.allocRegOrMem(self.air.typeOfIndex(inst), false, inst);
1053 const stack_mcv = try self.allocRegOrMem(self.typeOfIndex(inst), false, inst);
10531054 log.debug("spilling {} (%{d}) to stack mcv {any}", .{ reg, inst, stack_mcv });
10541055
10551056 const reg_mcv = self.getResolvedInstValue(inst);
......@@ -1063,14 +1064,14 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
10631064
10641065 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
10651066 try branch.inst_table.put(self.gpa, inst, stack_mcv);
1066 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
1067 try self.genSetStack(self.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
10671068}
10681069
10691070/// Save the current instruction stored in the compare flags if
10701071/// occupied
10711072fn spillCompareFlagsIfOccupied(self: *Self) !void {
10721073 if (self.cpsr_flags_inst) |inst_to_save| {
1073 const ty = self.air.typeOfIndex(inst_to_save);
1074 const ty = self.typeOfIndex(inst_to_save);
10741075 const mcv = self.getResolvedInstValue(inst_to_save);
10751076 const new_mcv = switch (mcv) {
10761077 .cpsr_flags => try self.allocRegOrMem(ty, true, inst_to_save),
......@@ -1080,7 +1081,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
10801081 else => unreachable, // mcv doesn't occupy the compare flags
10811082 };
10821083
1083 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
1084 try self.setRegOrMem(self.typeOfIndex(inst_to_save), new_mcv, mcv);
10841085 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
10851086
10861087 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -1114,17 +1115,14 @@ fn airAlloc(self: *Self, inst: Air.Inst.Index) !void {
11141115}
11151116
11161117fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
1118 const mod = self.bin_file.options.module.?;
11171119 const result: MCValue = switch (self.ret_mcv) {
11181120 .none, .register => .{ .ptr_stack_offset = try self.allocMemPtr(inst) },
11191121 .stack_offset => blk: {
11201122 // self.ret_mcv is an address to where this function
11211123 // should store its result into
1122 const ret_ty = self.fn_type.fnReturnType();
1123 var ptr_ty_payload: Type.Payload.ElemType = .{
1124 .base = .{ .tag = .single_mut_pointer },
1125 .data = ret_ty,
1126 };
1127 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
1124 const ret_ty = self.fn_type.fnReturnType(mod);
1125 const ptr_ty = try mod.singleMutPtrType(ret_ty);
11281126
11291127 // addr_reg will contain the address of where to store the
11301128 // result into
......@@ -1150,18 +1148,19 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
11501148}
11511149
11521150fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1151 const mod = self.bin_file.options.module.?;
11531152 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
11541153 if (self.liveness.isUnused(inst))
11551154 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
11561155
11571156 const operand = try self.resolveInst(ty_op.operand);
1158 const operand_ty = self.air.typeOf(ty_op.operand);
1159 const dest_ty = self.air.typeOfIndex(inst);
1157 const operand_ty = self.typeOf(ty_op.operand);
1158 const dest_ty = self.typeOfIndex(inst);
11601159
1161 const operand_abi_size = operand_ty.abiSize(self.target.*);
1162 const dest_abi_size = dest_ty.abiSize(self.target.*);
1163 const info_a = operand_ty.intInfo(self.target.*);
1164 const info_b = dest_ty.intInfo(self.target.*);
1160 const operand_abi_size = operand_ty.abiSize(mod);
1161 const dest_abi_size = dest_ty.abiSize(mod);
1162 const info_a = operand_ty.intInfo(mod);
1163 const info_b = dest_ty.intInfo(mod);
11651164
11661165 const dst_mcv: MCValue = blk: {
11671166 if (info_a.bits == info_b.bits) {
......@@ -1215,8 +1214,9 @@ fn trunc(
12151214 operand_ty: Type,
12161215 dest_ty: Type,
12171216) !MCValue {
1218 const info_a = operand_ty.intInfo(self.target.*);
1219 const info_b = dest_ty.intInfo(self.target.*);
1217 const mod = self.bin_file.options.module.?;
1218 const info_a = operand_ty.intInfo(mod);
1219 const info_b = dest_ty.intInfo(mod);
12201220
12211221 if (info_b.bits <= 32) {
12221222 if (info_a.bits > 32) {
......@@ -1259,8 +1259,8 @@ fn trunc(
12591259fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
12601260 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
12611261 const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
1262 const operand_ty = self.air.typeOf(ty_op.operand);
1263 const dest_ty = self.air.typeOfIndex(inst);
1262 const operand_ty = self.typeOf(ty_op.operand);
1263 const dest_ty = self.typeOfIndex(inst);
12641264
12651265 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
12661266 break :blk try self.trunc(inst, operand_bind, operand_ty, dest_ty);
......@@ -1278,15 +1278,16 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
12781278
12791279fn airNot(self: *Self, inst: Air.Inst.Index) !void {
12801280 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1281 const mod = self.bin_file.options.module.?;
12811282 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
12821283 const operand_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
1283 const operand_ty = self.air.typeOf(ty_op.operand);
1284 const operand_ty = self.typeOf(ty_op.operand);
12841285 switch (try operand_bind.resolveToMcv(self)) {
12851286 .dead => unreachable,
12861287 .unreach => unreachable,
12871288 .cpsr_flags => |cond| break :result MCValue{ .cpsr_flags = cond.negate() },
12881289 else => {
1289 switch (operand_ty.zigTypeTag()) {
1290 switch (operand_ty.zigTypeTag(mod)) {
12901291 .Bool => {
12911292 var op_reg: Register = undefined;
12921293 var dest_reg: Register = undefined;
......@@ -1319,7 +1320,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
13191320 },
13201321 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
13211322 .Int => {
1322 const int_info = operand_ty.intInfo(self.target.*);
1323 const int_info = operand_ty.intInfo(mod);
13231324 if (int_info.bits <= 32) {
13241325 var op_reg: Register = undefined;
13251326 var dest_reg: Register = undefined;
......@@ -1373,13 +1374,13 @@ fn minMax(
13731374 rhs_ty: Type,
13741375 maybe_inst: ?Air.Inst.Index,
13751376) !MCValue {
1376 switch (lhs_ty.zigTypeTag()) {
1377 const mod = self.bin_file.options.module.?;
1378 switch (lhs_ty.zigTypeTag(mod)) {
13771379 .Float => return self.fail("TODO ARM min/max on floats", .{}),
13781380 .Vector => return self.fail("TODO ARM min/max on vectors", .{}),
13791381 .Int => {
1380 const mod = self.bin_file.options.module.?;
13811382 assert(lhs_ty.eql(rhs_ty, mod));
1382 const int_info = lhs_ty.intInfo(self.target.*);
1383 const int_info = lhs_ty.intInfo(mod);
13831384 if (int_info.bits <= 32) {
13841385 var lhs_reg: Register = undefined;
13851386 var rhs_reg: Register = undefined;
......@@ -1463,8 +1464,8 @@ fn minMax(
14631464fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
14641465 const tag = self.air.instructions.items(.tag)[inst];
14651466 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1466 const lhs_ty = self.air.typeOf(bin_op.lhs);
1467 const rhs_ty = self.air.typeOf(bin_op.rhs);
1467 const lhs_ty = self.typeOf(bin_op.lhs);
1468 const rhs_ty = self.typeOf(bin_op.rhs);
14681469
14691470 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
14701471 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
......@@ -1483,9 +1484,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
14831484 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
14841485 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
14851486 const ptr = try self.resolveInst(bin_op.lhs);
1486 const ptr_ty = self.air.typeOf(bin_op.lhs);
1487 const ptr_ty = self.typeOf(bin_op.lhs);
14871488 const len = try self.resolveInst(bin_op.rhs);
1488 const len_ty = self.air.typeOf(bin_op.rhs);
1489 const len_ty = self.typeOf(bin_op.rhs);
14891490
14901491 const stack_offset = try self.allocMem(8, 4, inst);
14911492 try self.genSetStack(ptr_ty, stack_offset, ptr);
......@@ -1497,8 +1498,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
14971498
14981499fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
14991500 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1500 const lhs_ty = self.air.typeOf(bin_op.lhs);
1501 const rhs_ty = self.air.typeOf(bin_op.rhs);
1501 const lhs_ty = self.typeOf(bin_op.lhs);
1502 const rhs_ty = self.typeOf(bin_op.rhs);
15021503
15031504 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
15041505 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
......@@ -1548,8 +1549,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
15481549fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
15491550 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
15501551 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1551 const lhs_ty = self.air.typeOf(bin_op.lhs);
1552 const rhs_ty = self.air.typeOf(bin_op.rhs);
1552 const lhs_ty = self.typeOf(bin_op.lhs);
1553 const rhs_ty = self.typeOf(bin_op.rhs);
15531554
15541555 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
15551556 const lhs_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
......@@ -1582,23 +1583,23 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
15821583 const tag = self.air.instructions.items(.tag)[inst];
15831584 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
15841585 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
1586 const mod = self.bin_file.options.module.?;
15851587 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
15861588 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
15871589 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
1588 const lhs_ty = self.air.typeOf(extra.lhs);
1589 const rhs_ty = self.air.typeOf(extra.rhs);
1590 const lhs_ty = self.typeOf(extra.lhs);
1591 const rhs_ty = self.typeOf(extra.rhs);
15901592
1591 const tuple_ty = self.air.typeOfIndex(inst);
1592 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
1593 const tuple_align = tuple_ty.abiAlignment(self.target.*);
1594 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
1593 const tuple_ty = self.typeOfIndex(inst);
1594 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
1595 const tuple_align = tuple_ty.abiAlignment(mod);
1596 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
15951597
1596 switch (lhs_ty.zigTypeTag()) {
1598 switch (lhs_ty.zigTypeTag(mod)) {
15971599 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
15981600 .Int => {
1599 const mod = self.bin_file.options.module.?;
16001601 assert(lhs_ty.eql(rhs_ty, mod));
1601 const int_info = lhs_ty.intInfo(self.target.*);
1602 const int_info = lhs_ty.intInfo(mod);
16021603 if (int_info.bits < 32) {
16031604 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
16041605
......@@ -1631,7 +1632,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
16311632 });
16321633
16331634 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1634 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
1635 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
16351636
16361637 break :result MCValue{ .stack_offset = stack_offset };
16371638 } else if (int_info.bits == 32) {
......@@ -1695,23 +1696,23 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
16951696 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
16961697 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
16971698 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1699 const mod = self.bin_file.options.module.?;
16981700 const result: MCValue = result: {
16991701 const lhs_bind: ReadArg.Bind = .{ .inst = extra.lhs };
17001702 const rhs_bind: ReadArg.Bind = .{ .inst = extra.rhs };
1701 const lhs_ty = self.air.typeOf(extra.lhs);
1702 const rhs_ty = self.air.typeOf(extra.rhs);
1703 const lhs_ty = self.typeOf(extra.lhs);
1704 const rhs_ty = self.typeOf(extra.rhs);
17031705
1704 const tuple_ty = self.air.typeOfIndex(inst);
1705 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
1706 const tuple_align = tuple_ty.abiAlignment(self.target.*);
1707 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
1706 const tuple_ty = self.typeOfIndex(inst);
1707 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
1708 const tuple_align = tuple_ty.abiAlignment(mod);
1709 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
17081710
1709 switch (lhs_ty.zigTypeTag()) {
1711 switch (lhs_ty.zigTypeTag(mod)) {
17101712 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
17111713 .Int => {
1712 const mod = self.bin_file.options.module.?;
17131714 assert(lhs_ty.eql(rhs_ty, mod));
1714 const int_info = lhs_ty.intInfo(self.target.*);
1715 const int_info = lhs_ty.intInfo(mod);
17151716 if (int_info.bits <= 16) {
17161717 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
17171718
......@@ -1744,7 +1745,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
17441745 });
17451746
17461747 try self.genSetStack(lhs_ty, stack_offset, .{ .register = truncated_reg });
1747 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
1748 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
17481749
17491750 break :result MCValue{ .stack_offset = stack_offset };
17501751 } else if (int_info.bits <= 32) {
......@@ -1842,7 +1843,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
18421843 });
18431844
18441845 // strb rdlo, [...]
1845 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .register = rdlo });
1846 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .register = rdlo });
18461847
18471848 break :result MCValue{ .stack_offset = stack_offset };
18481849 } else {
......@@ -1859,19 +1860,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
18591860 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
18601861 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
18611862 if (self.liveness.isUnused(inst)) return self.finishAir(inst, .dead, .{ extra.lhs, extra.rhs, .none });
1863 const mod = self.bin_file.options.module.?;
18621864 const result: MCValue = result: {
1863 const lhs_ty = self.air.typeOf(extra.lhs);
1864 const rhs_ty = self.air.typeOf(extra.rhs);
1865 const lhs_ty = self.typeOf(extra.lhs);
1866 const rhs_ty = self.typeOf(extra.rhs);
18651867
1866 const tuple_ty = self.air.typeOfIndex(inst);
1867 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
1868 const tuple_align = tuple_ty.abiAlignment(self.target.*);
1869 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, self.target.*));
1868 const tuple_ty = self.typeOfIndex(inst);
1869 const tuple_size = @intCast(u32, tuple_ty.abiSize(mod));
1870 const tuple_align = tuple_ty.abiAlignment(mod);
1871 const overflow_bit_offset = @intCast(u32, tuple_ty.structFieldOffset(1, mod));
18701872
1871 switch (lhs_ty.zigTypeTag()) {
1873 switch (lhs_ty.zigTypeTag(mod)) {
18721874 .Vector => return self.fail("TODO implement shl_with_overflow for vectors", .{}),
18731875 .Int => {
1874 const int_info = lhs_ty.intInfo(self.target.*);
1876 const int_info = lhs_ty.intInfo(mod);
18751877 if (int_info.bits <= 32) {
18761878 const stack_offset = try self.allocMem(tuple_size, tuple_align, inst);
18771879
......@@ -1976,7 +1978,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
19761978 });
19771979
19781980 try self.genSetStack(lhs_ty, stack_offset, .{ .register = dest_reg });
1979 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
1981 try self.genSetStack(Type.u1, stack_offset - overflow_bit_offset, .{ .cpsr_flags = .ne });
19801982
19811983 break :result MCValue{ .stack_offset = stack_offset };
19821984 } else {
......@@ -2014,10 +2016,11 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
20142016}
20152017
20162018fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2019 const mod = self.bin_file.options.module.?;
20172020 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
20182021 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2019 const optional_ty = self.air.typeOfIndex(inst);
2020 const abi_size = @intCast(u32, optional_ty.abiSize(self.target.*));
2022 const optional_ty = self.typeOfIndex(inst);
2023 const abi_size = @intCast(u32, optional_ty.abiSize(mod));
20212024
20222025 // Optional with a zero-bit payload type is just a boolean true
20232026 if (abi_size == 1) {
......@@ -2036,16 +2039,17 @@ fn errUnionErr(
20362039 error_union_ty: Type,
20372040 maybe_inst: ?Air.Inst.Index,
20382041) !MCValue {
2039 const err_ty = error_union_ty.errorUnionSet();
2040 const payload_ty = error_union_ty.errorUnionPayload();
2041 if (err_ty.errorSetIsEmpty()) {
2042 const mod = self.bin_file.options.module.?;
2043 const err_ty = error_union_ty.errorUnionSet(mod);
2044 const payload_ty = error_union_ty.errorUnionPayload(mod);
2045 if (err_ty.errorSetIsEmpty(mod)) {
20422046 return MCValue{ .immediate = 0 };
20432047 }
2044 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2048 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
20452049 return try error_union_bind.resolveToMcv(self);
20462050 }
20472051
2048 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, self.target.*));
2052 const err_offset = @intCast(u32, errUnionErrorOffset(payload_ty, mod));
20492053 switch (try error_union_bind.resolveToMcv(self)) {
20502054 .register => {
20512055 var operand_reg: Register = undefined;
......@@ -2067,7 +2071,7 @@ fn errUnionErr(
20672071 );
20682072
20692073 const err_bit_offset = err_offset * 8;
2070 const err_bit_size = @intCast(u32, err_ty.abiSize(self.target.*)) * 8;
2074 const err_bit_size = @intCast(u32, err_ty.abiSize(mod)) * 8;
20712075
20722076 _ = try self.addInst(.{
20732077 .tag = .ubfx, // errors are unsigned integers
......@@ -2098,7 +2102,7 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
20982102 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
20992103 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
21002104 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
2101 const error_union_ty = self.air.typeOf(ty_op.operand);
2105 const error_union_ty = self.typeOf(ty_op.operand);
21022106
21032107 break :result try self.errUnionErr(error_union_bind, error_union_ty, inst);
21042108 };
......@@ -2112,16 +2116,17 @@ fn errUnionPayload(
21122116 error_union_ty: Type,
21132117 maybe_inst: ?Air.Inst.Index,
21142118) !MCValue {
2115 const err_ty = error_union_ty.errorUnionSet();
2116 const payload_ty = error_union_ty.errorUnionPayload();
2117 if (err_ty.errorSetIsEmpty()) {
2119 const mod = self.bin_file.options.module.?;
2120 const err_ty = error_union_ty.errorUnionSet(mod);
2121 const payload_ty = error_union_ty.errorUnionPayload(mod);
2122 if (err_ty.errorSetIsEmpty(mod)) {
21182123 return try error_union_bind.resolveToMcv(self);
21192124 }
2120 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2125 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
21212126 return MCValue.none;
21222127 }
21232128
2124 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));
2129 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
21252130 switch (try error_union_bind.resolveToMcv(self)) {
21262131 .register => {
21272132 var operand_reg: Register = undefined;
......@@ -2143,10 +2148,10 @@ fn errUnionPayload(
21432148 );
21442149
21452150 const payload_bit_offset = payload_offset * 8;
2146 const payload_bit_size = @intCast(u32, payload_ty.abiSize(self.target.*)) * 8;
2151 const payload_bit_size = @intCast(u32, payload_ty.abiSize(mod)) * 8;
21472152
21482153 _ = try self.addInst(.{
2149 .tag = if (payload_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx,
2154 .tag = if (payload_ty.isSignedInt(mod)) Mir.Inst.Tag.sbfx else .ubfx,
21502155 .data = .{ .rr_lsb_width = .{
21512156 .rd = dest_reg,
21522157 .rn = operand_reg,
......@@ -2174,7 +2179,7 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
21742179 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
21752180 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
21762181 const error_union_bind: ReadArg.Bind = .{ .inst = ty_op.operand };
2177 const error_union_ty = self.air.typeOf(ty_op.operand);
2182 const error_union_ty = self.typeOf(ty_op.operand);
21782183
21792184 break :result try self.errUnionPayload(error_union_bind, error_union_ty, inst);
21802185 };
......@@ -2221,19 +2226,20 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
22212226
22222227/// T to E!T
22232228fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
2229 const mod = self.bin_file.options.module.?;
22242230 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
22252231 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
22262232 const error_union_ty = self.air.getRefType(ty_op.ty);
2227 const error_ty = error_union_ty.errorUnionSet();
2228 const payload_ty = error_union_ty.errorUnionPayload();
2233 const error_ty = error_union_ty.errorUnionSet(mod);
2234 const payload_ty = error_union_ty.errorUnionPayload(mod);
22292235 const operand = try self.resolveInst(ty_op.operand);
2230 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;
2236 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
22312237
2232 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
2233 const abi_align = error_union_ty.abiAlignment(self.target.*);
2238 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
2239 const abi_align = error_union_ty.abiAlignment(mod);
22342240 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));
2235 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
2236 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
2241 const payload_off = errUnionPayloadOffset(payload_ty, mod);
2242 const err_off = errUnionErrorOffset(payload_ty, mod);
22372243 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), operand);
22382244 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), .{ .immediate = 0 });
22392245
......@@ -2244,19 +2250,20 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
22442250
22452251/// E to E!T
22462252fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2253 const mod = self.bin_file.options.module.?;
22472254 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
22482255 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
22492256 const error_union_ty = self.air.getRefType(ty_op.ty);
2250 const error_ty = error_union_ty.errorUnionSet();
2251 const payload_ty = error_union_ty.errorUnionPayload();
2257 const error_ty = error_union_ty.errorUnionSet(mod);
2258 const payload_ty = error_union_ty.errorUnionPayload(mod);
22522259 const operand = try self.resolveInst(ty_op.operand);
2253 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result operand;
2260 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result operand;
22542261
2255 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
2256 const abi_align = error_union_ty.abiAlignment(self.target.*);
2262 const abi_size = @intCast(u32, error_union_ty.abiSize(mod));
2263 const abi_align = error_union_ty.abiAlignment(mod);
22572264 const stack_offset = @intCast(u32, try self.allocMem(abi_size, abi_align, inst));
2258 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
2259 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
2265 const payload_off = errUnionPayloadOffset(payload_ty, mod);
2266 const err_off = errUnionErrorOffset(payload_ty, mod);
22602267 try self.genSetStack(error_ty, stack_offset - @intCast(u32, err_off), operand);
22612268 try self.genSetStack(payload_ty, stack_offset - @intCast(u32, payload_off), .undef);
22622269
......@@ -2360,8 +2367,9 @@ fn ptrElemVal(
23602367 ptr_ty: Type,
23612368 maybe_inst: ?Air.Inst.Index,
23622369) !MCValue {
2363 const elem_ty = ptr_ty.childType();
2364 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2370 const mod = self.bin_file.options.module.?;
2371 const elem_ty = ptr_ty.childType(mod);
2372 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
23652373
23662374 switch (elem_size) {
23672375 1, 4 => {
......@@ -2418,11 +2426,11 @@ fn ptrElemVal(
24182426}
24192427
24202428fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2429 const mod = self.bin_file.options.module.?;
24212430 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2422 const slice_ty = self.air.typeOf(bin_op.lhs);
2423 const result: MCValue = if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2424 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2425 const ptr_ty = slice_ty.slicePtrFieldType(&buf);
2431 const slice_ty = self.typeOf(bin_op.lhs);
2432 const result: MCValue = if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
2433 const ptr_ty = slice_ty.slicePtrFieldType(mod);
24262434
24272435 const slice_mcv = try self.resolveInst(bin_op.lhs);
24282436 const base_mcv = slicePtr(slice_mcv);
......@@ -2445,8 +2453,8 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
24452453 const base_bind: ReadArg.Bind = .{ .mcv = base_mcv };
24462454 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
24472455
2448 const slice_ty = self.air.typeOf(extra.lhs);
2449 const index_ty = self.air.typeOf(extra.rhs);
2456 const slice_ty = self.typeOf(extra.lhs);
2457 const index_ty = self.typeOf(extra.rhs);
24502458
24512459 const addr = try self.ptrArithmetic(.ptr_add, base_bind, index_bind, slice_ty, index_ty, null);
24522460 break :result addr;
......@@ -2461,7 +2469,8 @@ fn arrayElemVal(
24612469 array_ty: Type,
24622470 maybe_inst: ?Air.Inst.Index,
24632471) InnerError!MCValue {
2464 const elem_ty = array_ty.childType();
2472 const mod = self.bin_file.options.module.?;
2473 const elem_ty = array_ty.childType(mod);
24652474
24662475 const mcv = try array_bind.resolveToMcv(self);
24672476 switch (mcv) {
......@@ -2495,11 +2504,7 @@ fn arrayElemVal(
24952504
24962505 const base_bind: ReadArg.Bind = .{ .mcv = ptr_to_mcv };
24972506
2498 var ptr_ty_payload: Type.Payload.ElemType = .{
2499 .base = .{ .tag = .single_mut_pointer },
2500 .data = elem_ty,
2501 };
2502 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2507 const ptr_ty = try mod.singleMutPtrType(elem_ty);
25032508
25042509 return try self.ptrElemVal(base_bind, index_bind, ptr_ty, maybe_inst);
25052510 },
......@@ -2512,7 +2517,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
25122517 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
25132518 const array_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
25142519 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
2515 const array_ty = self.air.typeOf(bin_op.lhs);
2520 const array_ty = self.typeOf(bin_op.lhs);
25162521
25172522 break :result try self.arrayElemVal(array_bind, index_bind, array_ty, inst);
25182523 };
......@@ -2520,9 +2525,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
25202525}
25212526
25222527fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
2528 const mod = self.bin_file.options.module.?;
25232529 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2524 const ptr_ty = self.air.typeOf(bin_op.lhs);
2525 const result: MCValue = if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) .dead else result: {
2530 const ptr_ty = self.typeOf(bin_op.lhs);
2531 const result: MCValue = if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) .dead else result: {
25262532 const base_bind: ReadArg.Bind = .{ .inst = bin_op.lhs };
25272533 const index_bind: ReadArg.Bind = .{ .inst = bin_op.rhs };
25282534
......@@ -2538,8 +2544,8 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
25382544 const ptr_bind: ReadArg.Bind = .{ .inst = extra.lhs };
25392545 const index_bind: ReadArg.Bind = .{ .inst = extra.rhs };
25402546
2541 const ptr_ty = self.air.typeOf(extra.lhs);
2542 const index_ty = self.air.typeOf(extra.rhs);
2547 const ptr_ty = self.typeOf(extra.lhs);
2548 const index_ty = self.typeOf(extra.rhs);
25432549
25442550 const addr = try self.ptrArithmetic(.ptr_add, ptr_bind, index_bind, ptr_ty, index_ty, null);
25452551 break :result addr;
......@@ -2646,8 +2652,9 @@ fn reuseOperand(
26462652}
26472653
26482654fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
2649 const elem_ty = ptr_ty.elemType();
2650 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
2655 const mod = self.bin_file.options.module.?;
2656 const elem_ty = ptr_ty.childType(mod);
2657 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
26512658
26522659 switch (ptr) {
26532660 .none => unreachable,
......@@ -2722,19 +2729,20 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
27222729}
27232730
27242731fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2732 const mod = self.bin_file.options.module.?;
27252733 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2726 const elem_ty = self.air.typeOfIndex(inst);
2734 const elem_ty = self.typeOfIndex(inst);
27272735 const result: MCValue = result: {
2728 if (!elem_ty.hasRuntimeBits())
2736 if (!elem_ty.hasRuntimeBits(mod))
27292737 break :result MCValue.none;
27302738
27312739 const ptr = try self.resolveInst(ty_op.operand);
2732 const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
2740 const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(mod);
27332741 if (self.liveness.isUnused(inst) and !is_volatile)
27342742 break :result MCValue.dead;
27352743
27362744 const dest_mcv: MCValue = blk: {
2737 const ptr_fits_dest = elem_ty.abiSize(self.target.*) <= 4;
2745 const ptr_fits_dest = elem_ty.abiSize(mod) <= 4;
27382746 if (ptr_fits_dest and self.reuseOperand(inst, ty_op.operand, 0, ptr)) {
27392747 // The MCValue that holds the pointer can be re-used as the value.
27402748 break :blk ptr;
......@@ -2742,7 +2750,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
27422750 break :blk try self.allocRegOrMem(elem_ty, true, inst);
27432751 }
27442752 };
2745 try self.load(dest_mcv, ptr, self.air.typeOf(ty_op.operand));
2753 try self.load(dest_mcv, ptr, self.typeOf(ty_op.operand));
27462754
27472755 break :result dest_mcv;
27482756 };
......@@ -2750,7 +2758,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
27502758}
27512759
27522760fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
2753 const elem_size = @intCast(u32, value_ty.abiSize(self.target.*));
2761 const mod = self.bin_file.options.module.?;
2762 const elem_size = @intCast(u32, value_ty.abiSize(mod));
27542763
27552764 switch (ptr) {
27562765 .none => unreachable,
......@@ -2846,8 +2855,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
28462855 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
28472856 const ptr = try self.resolveInst(bin_op.lhs);
28482857 const value = try self.resolveInst(bin_op.rhs);
2849 const ptr_ty = self.air.typeOf(bin_op.lhs);
2850 const value_ty = self.air.typeOf(bin_op.rhs);
2858 const ptr_ty = self.typeOf(bin_op.lhs);
2859 const value_ty = self.typeOf(bin_op.rhs);
28512860
28522861 try self.store(ptr, value, ptr_ty, value_ty);
28532862
......@@ -2869,10 +2878,11 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
28692878
28702879fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
28712880 return if (self.liveness.isUnused(inst)) .dead else result: {
2881 const mod = self.bin_file.options.module.?;
28722882 const mcv = try self.resolveInst(operand);
2873 const ptr_ty = self.air.typeOf(operand);
2874 const struct_ty = ptr_ty.childType();
2875 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
2883 const ptr_ty = self.typeOf(operand);
2884 const struct_ty = ptr_ty.childType(mod);
2885 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
28762886 switch (mcv) {
28772887 .ptr_stack_offset => |off| {
28782888 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
......@@ -2892,11 +2902,12 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
28922902 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
28932903 const operand = extra.struct_operand;
28942904 const index = extra.field_index;
2905 const mod = self.bin_file.options.module.?;
28952906 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
28962907 const mcv = try self.resolveInst(operand);
2897 const struct_ty = self.air.typeOf(operand);
2898 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
2899 const struct_field_ty = struct_ty.structFieldType(index);
2908 const struct_ty = self.typeOf(operand);
2909 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
2910 const struct_field_ty = struct_ty.structFieldType(index, mod);
29002911
29012912 switch (mcv) {
29022913 .dead, .unreach => unreachable,
......@@ -2959,10 +2970,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
29592970 );
29602971
29612972 const field_bit_offset = struct_field_offset * 8;
2962 const field_bit_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)) * 8;
2973 const field_bit_size = @intCast(u32, struct_field_ty.abiSize(mod)) * 8;
29632974
29642975 _ = try self.addInst(.{
2965 .tag = if (struct_field_ty.isSignedInt()) Mir.Inst.Tag.sbfx else .ubfx,
2976 .tag = if (struct_field_ty.isSignedInt(mod)) Mir.Inst.Tag.sbfx else .ubfx,
29662977 .data = .{ .rr_lsb_width = .{
29672978 .rd = dest_reg,
29682979 .rn = operand_reg,
......@@ -2981,17 +2992,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
29812992}
29822993
29832994fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
2995 const mod = self.bin_file.options.module.?;
29842996 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
29852997 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
29862998 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
29872999 const field_ptr = try self.resolveInst(extra.field_ptr);
2988 const struct_ty = self.air.getRefType(ty_pl.ty).childType();
3000 const struct_ty = self.air.getRefType(ty_pl.ty).childType(mod);
29893001
2990 if (struct_ty.zigTypeTag() == .Union) {
3002 if (struct_ty.zigTypeTag(mod) == .Union) {
29913003 return self.fail("TODO implement @fieldParentPtr codegen for unions", .{});
29923004 }
29933005
2994 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, self.target.*));
3006 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(extra.field_index, mod));
29953007 switch (field_ptr) {
29963008 .ptr_stack_offset => |off| {
29973009 break :result MCValue{ .ptr_stack_offset = off + struct_field_offset };
......@@ -3375,12 +3387,12 @@ fn addSub(
33753387 maybe_inst: ?Air.Inst.Index,
33763388) InnerError!MCValue {
33773389 const mod = self.bin_file.options.module.?;
3378 switch (lhs_ty.zigTypeTag()) {
3390 switch (lhs_ty.zigTypeTag(mod)) {
33793391 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
33803392 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
33813393 .Int => {
33823394 assert(lhs_ty.eql(rhs_ty, mod));
3383 const int_info = lhs_ty.intInfo(self.target.*);
3395 const int_info = lhs_ty.intInfo(mod);
33843396 if (int_info.bits <= 32) {
33853397 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
33863398 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
......@@ -3431,12 +3443,12 @@ fn mul(
34313443 maybe_inst: ?Air.Inst.Index,
34323444) InnerError!MCValue {
34333445 const mod = self.bin_file.options.module.?;
3434 switch (lhs_ty.zigTypeTag()) {
3446 switch (lhs_ty.zigTypeTag(mod)) {
34353447 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
34363448 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
34373449 .Int => {
34383450 assert(lhs_ty.eql(rhs_ty, mod));
3439 const int_info = lhs_ty.intInfo(self.target.*);
3451 const int_info = lhs_ty.intInfo(mod);
34403452 if (int_info.bits <= 32) {
34413453 // TODO add optimisations for multiplication
34423454 // with immediates, for example a * 2 can be
......@@ -3463,7 +3475,8 @@ fn divFloat(
34633475 _ = rhs_ty;
34643476 _ = maybe_inst;
34653477
3466 switch (lhs_ty.zigTypeTag()) {
3478 const mod = self.bin_file.options.module.?;
3479 switch (lhs_ty.zigTypeTag(mod)) {
34673480 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
34683481 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
34693482 else => unreachable,
......@@ -3479,12 +3492,12 @@ fn divTrunc(
34793492 maybe_inst: ?Air.Inst.Index,
34803493) InnerError!MCValue {
34813494 const mod = self.bin_file.options.module.?;
3482 switch (lhs_ty.zigTypeTag()) {
3495 switch (lhs_ty.zigTypeTag(mod)) {
34833496 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
34843497 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
34853498 .Int => {
34863499 assert(lhs_ty.eql(rhs_ty, mod));
3487 const int_info = lhs_ty.intInfo(self.target.*);
3500 const int_info = lhs_ty.intInfo(mod);
34883501 if (int_info.bits <= 32) {
34893502 switch (int_info.signedness) {
34903503 .signed => {
......@@ -3522,12 +3535,12 @@ fn divFloor(
35223535 maybe_inst: ?Air.Inst.Index,
35233536) InnerError!MCValue {
35243537 const mod = self.bin_file.options.module.?;
3525 switch (lhs_ty.zigTypeTag()) {
3538 switch (lhs_ty.zigTypeTag(mod)) {
35263539 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
35273540 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
35283541 .Int => {
35293542 assert(lhs_ty.eql(rhs_ty, mod));
3530 const int_info = lhs_ty.intInfo(self.target.*);
3543 const int_info = lhs_ty.intInfo(mod);
35313544 if (int_info.bits <= 32) {
35323545 switch (int_info.signedness) {
35333546 .signed => {
......@@ -3569,7 +3582,8 @@ fn divExact(
35693582 _ = rhs_ty;
35703583 _ = maybe_inst;
35713584
3572 switch (lhs_ty.zigTypeTag()) {
3585 const mod = self.bin_file.options.module.?;
3586 switch (lhs_ty.zigTypeTag(mod)) {
35733587 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
35743588 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
35753589 .Int => return self.fail("TODO ARM div_exact", .{}),
......@@ -3586,12 +3600,12 @@ fn rem(
35863600 maybe_inst: ?Air.Inst.Index,
35873601) InnerError!MCValue {
35883602 const mod = self.bin_file.options.module.?;
3589 switch (lhs_ty.zigTypeTag()) {
3603 switch (lhs_ty.zigTypeTag(mod)) {
35903604 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
35913605 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
35923606 .Int => {
35933607 assert(lhs_ty.eql(rhs_ty, mod));
3594 const int_info = lhs_ty.intInfo(self.target.*);
3608 const int_info = lhs_ty.intInfo(mod);
35953609 if (int_info.bits <= 32) {
35963610 switch (int_info.signedness) {
35973611 .signed => {
......@@ -3654,7 +3668,8 @@ fn modulo(
36543668 _ = rhs_ty;
36553669 _ = maybe_inst;
36563670
3657 switch (lhs_ty.zigTypeTag()) {
3671 const mod = self.bin_file.options.module.?;
3672 switch (lhs_ty.zigTypeTag(mod)) {
36583673 .Float => return self.fail("TODO ARM binary operations on floats", .{}),
36593674 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
36603675 .Int => return self.fail("TODO ARM mod", .{}),
......@@ -3671,10 +3686,11 @@ fn wrappingArithmetic(
36713686 rhs_ty: Type,
36723687 maybe_inst: ?Air.Inst.Index,
36733688) InnerError!MCValue {
3674 switch (lhs_ty.zigTypeTag()) {
3689 const mod = self.bin_file.options.module.?;
3690 switch (lhs_ty.zigTypeTag(mod)) {
36753691 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
36763692 .Int => {
3677 const int_info = lhs_ty.intInfo(self.target.*);
3693 const int_info = lhs_ty.intInfo(mod);
36783694 if (int_info.bits <= 32) {
36793695 // Generate an add/sub/mul
36803696 const result: MCValue = switch (tag) {
......@@ -3708,12 +3724,12 @@ fn bitwise(
37083724 rhs_ty: Type,
37093725 maybe_inst: ?Air.Inst.Index,
37103726) InnerError!MCValue {
3711 switch (lhs_ty.zigTypeTag()) {
3727 const mod = self.bin_file.options.module.?;
3728 switch (lhs_ty.zigTypeTag(mod)) {
37123729 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
37133730 .Int => {
3714 const mod = self.bin_file.options.module.?;
37153731 assert(lhs_ty.eql(rhs_ty, mod));
3716 const int_info = lhs_ty.intInfo(self.target.*);
3732 const int_info = lhs_ty.intInfo(mod);
37173733 if (int_info.bits <= 32) {
37183734 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
37193735 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
......@@ -3753,16 +3769,17 @@ fn shiftExact(
37533769 rhs_ty: Type,
37543770 maybe_inst: ?Air.Inst.Index,
37553771) InnerError!MCValue {
3756 switch (lhs_ty.zigTypeTag()) {
3772 const mod = self.bin_file.options.module.?;
3773 switch (lhs_ty.zigTypeTag(mod)) {
37573774 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
37583775 .Int => {
3759 const int_info = lhs_ty.intInfo(self.target.*);
3776 const int_info = lhs_ty.intInfo(mod);
37603777 if (int_info.bits <= 32) {
37613778 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
37623779
37633780 const mir_tag: Mir.Inst.Tag = switch (tag) {
37643781 .shl_exact => .lsl,
3765 .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
3782 .shr_exact => switch (lhs_ty.intInfo(mod).signedness) {
37663783 .signed => Mir.Inst.Tag.asr,
37673784 .unsigned => Mir.Inst.Tag.lsr,
37683785 },
......@@ -3791,10 +3808,11 @@ fn shiftNormal(
37913808 rhs_ty: Type,
37923809 maybe_inst: ?Air.Inst.Index,
37933810) InnerError!MCValue {
3794 switch (lhs_ty.zigTypeTag()) {
3811 const mod = self.bin_file.options.module.?;
3812 switch (lhs_ty.zigTypeTag(mod)) {
37953813 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
37963814 .Int => {
3797 const int_info = lhs_ty.intInfo(self.target.*);
3815 const int_info = lhs_ty.intInfo(mod);
37983816 if (int_info.bits <= 32) {
37993817 // Generate a shl_exact/shr_exact
38003818 const result: MCValue = switch (tag) {
......@@ -3833,7 +3851,8 @@ fn booleanOp(
38333851 rhs_ty: Type,
38343852 maybe_inst: ?Air.Inst.Index,
38353853) InnerError!MCValue {
3836 switch (lhs_ty.zigTypeTag()) {
3854 const mod = self.bin_file.options.module.?;
3855 switch (lhs_ty.zigTypeTag(mod)) {
38373856 .Bool => {
38383857 const lhs_immediate = try lhs_bind.resolveToImmediate(self);
38393858 const rhs_immediate = try rhs_bind.resolveToImmediate(self);
......@@ -3866,17 +3885,17 @@ fn ptrArithmetic(
38663885 rhs_ty: Type,
38673886 maybe_inst: ?Air.Inst.Index,
38683887) InnerError!MCValue {
3869 switch (lhs_ty.zigTypeTag()) {
3888 const mod = self.bin_file.options.module.?;
3889 switch (lhs_ty.zigTypeTag(mod)) {
38703890 .Pointer => {
3871 const mod = self.bin_file.options.module.?;
38723891 assert(rhs_ty.eql(Type.usize, mod));
38733892
38743893 const ptr_ty = lhs_ty;
3875 const elem_ty = switch (ptr_ty.ptrSize()) {
3876 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
3877 else => ptr_ty.childType(),
3894 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
3895 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
3896 else => ptr_ty.childType(mod),
38783897 };
3879 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
3898 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
38803899
38813900 const base_tag: Air.Inst.Tag = switch (tag) {
38823901 .ptr_add => .add,
......@@ -3903,11 +3922,12 @@ fn ptrArithmetic(
39033922}
39043923
39053924fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type) !void {
3906 const abi_size = ty.abiSize(self.target.*);
3925 const mod = self.bin_file.options.module.?;
3926 const abi_size = ty.abiSize(mod);
39073927
39083928 const tag: Mir.Inst.Tag = switch (abi_size) {
3909 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb,
3910 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh,
3929 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb else .ldrb,
3930 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh else .ldrh,
39113931 3, 4 => .ldr,
39123932 else => unreachable,
39133933 };
......@@ -3924,7 +3944,7 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type)
39243944 } };
39253945
39263946 const data: Mir.Inst.Data = switch (abi_size) {
3927 1 => if (ty.isSignedInt()) rr_extra_offset else rr_offset,
3947 1 => if (ty.isSignedInt(mod)) rr_extra_offset else rr_offset,
39283948 2 => rr_extra_offset,
39293949 3, 4 => rr_offset,
39303950 else => unreachable,
......@@ -3937,7 +3957,8 @@ fn genLdrRegister(self: *Self, dest_reg: Register, addr_reg: Register, ty: Type)
39373957}
39383958
39393959fn genStrRegister(self: *Self, source_reg: Register, addr_reg: Register, ty: Type) !void {
3940 const abi_size = ty.abiSize(self.target.*);
3960 const mod = self.bin_file.options.module.?;
3961 const abi_size = ty.abiSize(mod);
39413962
39423963 const tag: Mir.Inst.Tag = switch (abi_size) {
39433964 1 => .strb,
......@@ -4051,14 +4072,14 @@ fn genInlineMemset(
40514072) !void {
40524073 const dst_reg = switch (dst) {
40534074 .register => |r| r,
4054 else => try self.copyToTmpRegister(Type.initTag(.manyptr_u8), dst),
4075 else => try self.copyToTmpRegister(Type.manyptr_u8, dst),
40554076 };
40564077 const dst_reg_lock = self.register_manager.lockReg(dst_reg);
40574078 defer if (dst_reg_lock) |lock| self.register_manager.unlockReg(lock);
40584079
40594080 const val_reg = switch (val) {
40604081 .register => |r| r,
4061 else => try self.copyToTmpRegister(Type.initTag(.u8), val),
4082 else => try self.copyToTmpRegister(Type.u8, val),
40624083 };
40634084 const val_reg_lock = self.register_manager.lockReg(val_reg);
40644085 defer if (val_reg_lock) |lock| self.register_manager.unlockReg(lock);
......@@ -4143,7 +4164,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
41434164 while (self.args[arg_index] == .none) arg_index += 1;
41444165 self.arg_index = arg_index + 1;
41454166
4146 const ty = self.air.typeOfIndex(inst);
4167 const ty = self.typeOfIndex(inst);
41474168 const tag = self.air.instructions.items(.tag)[inst];
41484169 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
41494170 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
......@@ -4196,11 +4217,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
41964217 const callee = pl_op.operand;
41974218 const extra = self.air.extraData(Air.Call, pl_op.payload);
41984219 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
4199 const ty = self.air.typeOf(callee);
4220 const ty = self.typeOf(callee);
4221 const mod = self.bin_file.options.module.?;
42004222
4201 const fn_ty = switch (ty.zigTypeTag()) {
4223 const fn_ty = switch (ty.zigTypeTag(mod)) {
42024224 .Fn => ty,
4203 .Pointer => ty.childType(),
4225 .Pointer => ty.childType(mod),
42044226 else => unreachable,
42054227 };
42064228
......@@ -4225,16 +4247,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42254247 // untouched by the parameter passing code
42264248 const r0_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
42274249 log.debug("airCall: return by reference", .{});
4228 const ret_ty = fn_ty.fnReturnType();
4229 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4230 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
4250 const ret_ty = fn_ty.fnReturnType(mod);
4251 const ret_abi_size = @intCast(u32, ret_ty.abiSize(mod));
4252 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(mod));
42314253 const stack_offset = try self.allocMem(ret_abi_size, ret_abi_align, inst);
42324254
4233 var ptr_ty_payload: Type.Payload.ElemType = .{
4234 .base = .{ .tag = .single_mut_pointer },
4235 .data = ret_ty,
4236 };
4237 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4255 const ptr_ty = try mod.singleMutPtrType(ret_ty);
42384256 try self.register_manager.getReg(.r0, null);
42394257 try self.genSetReg(ptr_ty, .r0, .{ .ptr_stack_offset = stack_offset });
42404258
......@@ -4249,7 +4267,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42494267
42504268 for (info.args, 0..) |mc_arg, arg_i| {
42514269 const arg = args[arg_i];
4252 const arg_ty = self.air.typeOf(arg);
4270 const arg_ty = self.typeOf(arg);
42534271 const arg_mcv = try self.resolveInst(args[arg_i]);
42544272
42554273 switch (mc_arg) {
......@@ -4270,16 +4288,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42704288
42714289 // Due to incremental compilation, how function calls are generated depends
42724290 // on linking.
4273 if (self.air.value(callee)) |func_value| {
4274 if (func_value.castTag(.function)) |func_payload| {
4275 const func = func_payload.data;
4276
4291 if (try self.air.value(callee, mod)) |func_value| {
4292 if (func_value.getFunction(mod)) |func| {
42774293 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
42784294 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
42794295 const atom = elf_file.getAtom(atom_index);
42804296 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
42814297 const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));
4282 try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr });
4298 try self.genSetReg(Type.usize, .lr, .{ .memory = got_addr });
42834299 } else if (self.bin_file.cast(link.File.MachO)) |_| {
42844300 unreachable; // unsupported architecture for MachO
42854301 } else {
......@@ -4288,16 +4304,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
42884304 @tagName(self.target.cpu.arch),
42894305 });
42904306 }
4291 } else if (func_value.castTag(.extern_fn)) |_| {
4307 } else if (func_value.getExternFunc(mod)) |_| {
42924308 return self.fail("TODO implement calling extern functions", .{});
42934309 } else {
42944310 return self.fail("TODO implement calling bitcasted functions", .{});
42954311 }
42964312 } else {
4297 assert(ty.zigTypeTag() == .Pointer);
4313 assert(ty.zigTypeTag(mod) == .Pointer);
42984314 const mcv = try self.resolveInst(callee);
42994315
4300 try self.genSetReg(Type.initTag(.usize), .lr, mcv);
4316 try self.genSetReg(Type.usize, .lr, mcv);
43014317 }
43024318
43034319 // TODO: add Instruction.supportedOn
......@@ -4329,7 +4345,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43294345 if (RegisterManager.indexOfRegIntoTracked(reg) == null) {
43304346 // Save function return value into a tracked register
43314347 log.debug("airCall: copying {} as it is not tracked", .{reg});
4332 const new_reg = try self.copyToTmpRegister(fn_ty.fnReturnType(), info.return_value);
4348 const new_reg = try self.copyToTmpRegister(fn_ty.fnReturnType(mod), info.return_value);
43334349 break :result MCValue{ .register = new_reg };
43344350 }
43354351 },
......@@ -4353,14 +4369,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43534369}
43544370
43554371fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4372 const mod = self.bin_file.options.module.?;
43564373 const un_op = self.air.instructions.items(.data)[inst].un_op;
43574374 const operand = try self.resolveInst(un_op);
4358 const ret_ty = self.fn_type.fnReturnType();
4375 const ret_ty = self.fn_type.fnReturnType(mod);
43594376
43604377 switch (self.ret_mcv) {
43614378 .none => {},
43624379 .immediate => {
4363 assert(ret_ty.isError());
4380 assert(ret_ty.isError(mod));
43644381 },
43654382 .register => |reg| {
43664383 // Return result by value
......@@ -4371,11 +4388,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
43714388 //
43724389 // self.ret_mcv is an address to where this function
43734390 // should store its result into
4374 var ptr_ty_payload: Type.Payload.ElemType = .{
4375 .base = .{ .tag = .single_mut_pointer },
4376 .data = ret_ty,
4377 };
4378 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4391 const ptr_ty = try mod.singleMutPtrType(ret_ty);
43794392 try self.store(self.ret_mcv, operand, ptr_ty, ret_ty);
43804393 },
43814394 else => unreachable, // invalid return result
......@@ -4388,10 +4401,11 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
43884401}
43894402
43904403fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4404 const mod = self.bin_file.options.module.?;
43914405 const un_op = self.air.instructions.items(.data)[inst].un_op;
43924406 const ptr = try self.resolveInst(un_op);
4393 const ptr_ty = self.air.typeOf(un_op);
4394 const ret_ty = self.fn_type.fnReturnType();
4407 const ptr_ty = self.typeOf(un_op);
4408 const ret_ty = self.fn_type.fnReturnType(mod);
43954409
43964410 switch (self.ret_mcv) {
43974411 .none => {},
......@@ -4411,8 +4425,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44114425 // location.
44124426 const op_inst = Air.refToIndex(un_op).?;
44134427 if (self.air.instructions.items(.tag)[op_inst] != .ret_ptr) {
4414 const abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4415 const abi_align = ret_ty.abiAlignment(self.target.*);
4428 const abi_size = @intCast(u32, ret_ty.abiSize(mod));
4429 const abi_align = ret_ty.abiAlignment(mod);
44164430
44174431 const offset = try self.allocMem(abi_size, abi_align, null);
44184432
......@@ -4432,7 +4446,7 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
44324446
44334447fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
44344448 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4435 const lhs_ty = self.air.typeOf(bin_op.lhs);
4449 const lhs_ty = self.typeOf(bin_op.lhs);
44364450
44374451 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
44384452 break :blk try self.cmp(.{ .inst = bin_op.lhs }, .{ .inst = bin_op.rhs }, lhs_ty, op);
......@@ -4448,29 +4462,28 @@ fn cmp(
44484462 lhs_ty: Type,
44494463 op: math.CompareOperator,
44504464) !MCValue {
4451 var int_buffer: Type.Payload.Bits = undefined;
4452 const int_ty = switch (lhs_ty.zigTypeTag()) {
4465 const mod = self.bin_file.options.module.?;
4466 const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
44534467 .Optional => blk: {
4454 var opt_buffer: Type.Payload.ElemType = undefined;
4455 const payload_ty = lhs_ty.optionalChild(&opt_buffer);
4456 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4457 break :blk Type.initTag(.u1);
4458 } else if (lhs_ty.isPtrLikeOptional()) {
4468 const payload_ty = lhs_ty.optionalChild(mod);
4469 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4470 break :blk Type.u1;
4471 } else if (lhs_ty.isPtrLikeOptional(mod)) {
44594472 break :blk Type.usize;
44604473 } else {
44614474 return self.fail("TODO ARM cmp non-pointer optionals", .{});
44624475 }
44634476 },
44644477 .Float => return self.fail("TODO ARM cmp floats", .{}),
4465 .Enum => lhs_ty.intTagType(&int_buffer),
4478 .Enum => lhs_ty.intTagType(mod),
44664479 .Int => lhs_ty,
4467 .Bool => Type.initTag(.u1),
4480 .Bool => Type.u1,
44684481 .Pointer => Type.usize,
4469 .ErrorSet => Type.initTag(.u16),
4482 .ErrorSet => Type.u16,
44704483 else => unreachable,
44714484 };
44724485
4473 const int_info = int_ty.intInfo(self.target.*);
4486 const int_info = int_ty.intInfo(mod);
44744487 if (int_info.bits <= 32) {
44754488 try self.spillCompareFlagsIfOccupied();
44764489
......@@ -4555,8 +4568,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
45554568}
45564569
45574570fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
4558 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4559 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
4571 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
4572 const mod = self.bin_file.options.module.?;
4573 const function = mod.funcPtr(ty_fn.func);
45604574 // TODO emit debug info for function change
45614575 _ = function;
45624576 return self.finishAir(inst, .dead, .{ .none, .none, .none });
......@@ -4571,7 +4585,7 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
45714585 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
45724586 const operand = pl_op.operand;
45734587 const tag = self.air.instructions.items(.tag)[inst];
4574 const ty = self.air.typeOf(operand);
4588 const ty = self.typeOf(operand);
45754589 const mcv = try self.resolveInst(operand);
45764590 const name = self.air.nullTerminatedString(pl_op.payload);
45774591
......@@ -4636,8 +4650,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
46364650 // whether it needs to be spilled in the branches
46374651 if (self.liveness.operandDies(inst, 0)) {
46384652 const op_int = @enumToInt(pl_op.operand);
4639 if (op_int >= Air.Inst.Ref.typed_value_map.len) {
4640 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
4653 if (op_int >= Air.ref_start_index) {
4654 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
46414655 self.processDeath(op_index);
46424656 }
46434657 }
......@@ -4726,7 +4740,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
47264740 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
47274741 // TODO make sure the destination stack offset / register does not already have something
47284742 // going on there.
4729 try self.setRegOrMem(self.air.typeOfIndex(else_key), canon_mcv, else_value);
4743 try self.setRegOrMem(self.typeOfIndex(else_key), canon_mcv, else_value);
47304744 // TODO track the new register / stack allocation
47314745 }
47324746 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count());
......@@ -4753,7 +4767,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
47534767 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
47544768 // TODO make sure the destination stack offset / register does not already have something
47554769 // going on there.
4756 try self.setRegOrMem(self.air.typeOfIndex(then_key), parent_mcv, then_value);
4770 try self.setRegOrMem(self.typeOfIndex(then_key), parent_mcv, then_value);
47574771 // TODO track the new register / stack allocation
47584772 }
47594773
......@@ -4772,8 +4786,9 @@ fn isNull(
47724786 operand_bind: ReadArg.Bind,
47734787 operand_ty: Type,
47744788) !MCValue {
4775 if (operand_ty.isPtrLikeOptional()) {
4776 assert(operand_ty.abiSize(self.target.*) == 4);
4789 const mod = self.bin_file.options.module.?;
4790 if (operand_ty.isPtrLikeOptional(mod)) {
4791 assert(operand_ty.abiSize(mod) == 4);
47774792
47784793 const imm_bind: ReadArg.Bind = .{ .mcv = .{ .immediate = 0 } };
47794794 return self.cmp(operand_bind, imm_bind, Type.usize, .eq);
......@@ -4797,7 +4812,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
47974812 const un_op = self.air.instructions.items(.data)[inst].un_op;
47984813 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
47994814 const operand_bind: ReadArg.Bind = .{ .inst = un_op };
4800 const operand_ty = self.air.typeOf(un_op);
4815 const operand_ty = self.typeOf(un_op);
48014816
48024817 break :result try self.isNull(operand_bind, operand_ty);
48034818 };
......@@ -4805,11 +4820,12 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
48054820}
48064821
48074822fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4823 const mod = self.bin_file.options.module.?;
48084824 const un_op = self.air.instructions.items(.data)[inst].un_op;
48094825 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
48104826 const operand_ptr = try self.resolveInst(un_op);
4811 const ptr_ty = self.air.typeOf(un_op);
4812 const elem_ty = ptr_ty.elemType();
4827 const ptr_ty = self.typeOf(un_op);
4828 const elem_ty = ptr_ty.childType(mod);
48134829
48144830 const operand = try self.allocRegOrMem(elem_ty, true, null);
48154831 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4823,7 +4839,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
48234839 const un_op = self.air.instructions.items(.data)[inst].un_op;
48244840 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
48254841 const operand_bind: ReadArg.Bind = .{ .inst = un_op };
4826 const operand_ty = self.air.typeOf(un_op);
4842 const operand_ty = self.typeOf(un_op);
48274843
48284844 break :result try self.isNonNull(operand_bind, operand_ty);
48294845 };
......@@ -4831,11 +4847,12 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
48314847}
48324848
48334849fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4850 const mod = self.bin_file.options.module.?;
48344851 const un_op = self.air.instructions.items(.data)[inst].un_op;
48354852 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
48364853 const operand_ptr = try self.resolveInst(un_op);
4837 const ptr_ty = self.air.typeOf(un_op);
4838 const elem_ty = ptr_ty.elemType();
4854 const ptr_ty = self.typeOf(un_op);
4855 const elem_ty = ptr_ty.childType(mod);
48394856
48404857 const operand = try self.allocRegOrMem(elem_ty, true, null);
48414858 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4850,9 +4867,10 @@ fn isErr(
48504867 error_union_bind: ReadArg.Bind,
48514868 error_union_ty: Type,
48524869) !MCValue {
4853 const error_type = error_union_ty.errorUnionSet();
4870 const mod = self.bin_file.options.module.?;
4871 const error_type = error_union_ty.errorUnionSet(mod);
48544872
4855 if (error_type.errorSetIsEmpty()) {
4873 if (error_type.errorSetIsEmpty(mod)) {
48564874 return MCValue{ .immediate = 0 }; // always false
48574875 }
48584876
......@@ -4883,7 +4901,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
48834901 const un_op = self.air.instructions.items(.data)[inst].un_op;
48844902 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
48854903 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };
4886 const error_union_ty = self.air.typeOf(un_op);
4904 const error_union_ty = self.typeOf(un_op);
48874905
48884906 break :result try self.isErr(error_union_bind, error_union_ty);
48894907 };
......@@ -4891,11 +4909,12 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
48914909}
48924910
48934911fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4912 const mod = self.bin_file.options.module.?;
48944913 const un_op = self.air.instructions.items(.data)[inst].un_op;
48954914 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
48964915 const operand_ptr = try self.resolveInst(un_op);
4897 const ptr_ty = self.air.typeOf(un_op);
4898 const elem_ty = ptr_ty.elemType();
4916 const ptr_ty = self.typeOf(un_op);
4917 const elem_ty = ptr_ty.childType(mod);
48994918
49004919 const operand = try self.allocRegOrMem(elem_ty, true, null);
49014920 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4909,7 +4928,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
49094928 const un_op = self.air.instructions.items(.data)[inst].un_op;
49104929 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49114930 const error_union_bind: ReadArg.Bind = .{ .inst = un_op };
4912 const error_union_ty = self.air.typeOf(un_op);
4931 const error_union_ty = self.typeOf(un_op);
49134932
49144933 break :result try self.isNonErr(error_union_bind, error_union_ty);
49154934 };
......@@ -4917,11 +4936,12 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
49174936}
49184937
49194938fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4939 const mod = self.bin_file.options.module.?;
49204940 const un_op = self.air.instructions.items(.data)[inst].un_op;
49214941 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
49224942 const operand_ptr = try self.resolveInst(un_op);
4923 const ptr_ty = self.air.typeOf(un_op);
4924 const elem_ty = ptr_ty.elemType();
4943 const ptr_ty = self.typeOf(un_op);
4944 const elem_ty = ptr_ty.childType(mod);
49254945
49264946 const operand = try self.allocRegOrMem(elem_ty, true, null);
49274947 try self.load(operand, operand_ptr, ptr_ty);
......@@ -4988,7 +5008,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
49885008
49895009fn airSwitch(self: *Self, inst: Air.Inst.Index) !void {
49905010 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
4991 const condition_ty = self.air.typeOf(pl_op.operand);
5011 const condition_ty = self.typeOf(pl_op.operand);
49925012 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
49935013 const liveness = try self.liveness.getSwitchBr(
49945014 self.gpa,
......@@ -5131,9 +5151,10 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
51315151}
51325152
51335153fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
5154 const mod = self.bin_file.options.module.?;
51345155 const block_data = self.blocks.getPtr(block).?;
51355156
5136 if (self.air.typeOf(operand).hasRuntimeBits()) {
5157 if (self.typeOf(operand).hasRuntimeBits(mod)) {
51375158 const operand_mcv = try self.resolveInst(operand);
51385159 const block_mcv = block_data.mcv;
51395160 if (block_mcv == .none) {
......@@ -5141,14 +5162,14 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
51415162 .none, .dead, .unreach => unreachable,
51425163 .register, .stack_offset, .memory => operand_mcv,
51435164 .immediate, .stack_argument_offset, .cpsr_flags => blk: {
5144 const new_mcv = try self.allocRegOrMem(self.air.typeOfIndex(block), true, block);
5145 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
5165 const new_mcv = try self.allocRegOrMem(self.typeOfIndex(block), true, block);
5166 try self.setRegOrMem(self.typeOfIndex(block), new_mcv, operand_mcv);
51465167 break :blk new_mcv;
51475168 },
51485169 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
51495170 };
51505171 } else {
5151 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
5172 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
51525173 }
51535174 }
51545175 return self.brVoid(block);
......@@ -5212,7 +5233,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
52125233
52135234 const arg_mcv = try self.resolveInst(input);
52145235 try self.register_manager.getReg(reg, null);
5215 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
5236 try self.genSetReg(self.typeOf(input), reg, arg_mcv);
52165237 }
52175238
52185239 {
......@@ -5301,7 +5322,8 @@ fn setRegOrMem(self: *Self, ty: Type, loc: MCValue, val: MCValue) !void {
53015322}
53025323
53035324fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
5304 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5325 const mod = self.bin_file.options.module.?;
5326 const abi_size = @intCast(u32, ty.abiSize(mod));
53055327 switch (mcv) {
53065328 .dead => unreachable,
53075329 .unreach, .none => return, // Nothing to do.
......@@ -5332,7 +5354,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
53325354 1, 4 => {
53335355 const offset = if (math.cast(u12, stack_offset)) |imm| blk: {
53345356 break :blk Instruction.Offset.imm(imm);
5335 } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset }), .none);
5357 } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.u32, MCValue{ .immediate = stack_offset }), .none);
53365358
53375359 const tag: Mir.Inst.Tag = switch (abi_size) {
53385360 1 => .strb,
......@@ -5355,7 +5377,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
53555377 2 => {
53565378 const offset = if (stack_offset <= math.maxInt(u8)) blk: {
53575379 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, stack_offset));
5358 } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset }));
5380 } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.u32, MCValue{ .immediate = stack_offset }));
53595381
53605382 _ = try self.addInst(.{
53615383 .tag = .strh,
......@@ -5378,11 +5400,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
53785400 const reg_lock = self.register_manager.lockReg(reg);
53795401 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
53805402
5381 const wrapped_ty = ty.structFieldType(0);
5403 const wrapped_ty = ty.structFieldType(0, mod);
53825404 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });
53835405
5384 const overflow_bit_ty = ty.structFieldType(1);
5385 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
5406 const overflow_bit_ty = ty.structFieldType(1, mod);
5407 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
53865408 const cond_reg = try self.register_manager.allocReg(null, gp);
53875409
53885410 // C flag: movcs reg, #1
......@@ -5420,11 +5442,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54205442 const reg = try self.copyToTmpRegister(ty, mcv);
54215443 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
54225444 } else {
5423 var ptr_ty_payload: Type.Payload.ElemType = .{
5424 .base = .{ .tag = .single_mut_pointer },
5425 .data = ty,
5426 };
5427 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
5445 const ptr_ty = try mod.singleMutPtrType(ty);
54285446
54295447 // TODO call extern memcpy
54305448 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);
......@@ -5466,6 +5484,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54665484}
54675485
54685486fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
5487 const mod = self.bin_file.options.module.?;
54695488 switch (mcv) {
54705489 .dead => unreachable,
54715490 .unreach, .none => return, // Nothing to do.
......@@ -5640,17 +5659,17 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56405659 },
56415660 .stack_offset => |off| {
56425661 // TODO: maybe addressing from sp instead of fp
5643 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5662 const abi_size = @intCast(u32, ty.abiSize(mod));
56445663
56455664 const tag: Mir.Inst.Tag = switch (abi_size) {
5646 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb else .ldrb,
5647 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh else .ldrh,
5665 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb else .ldrb,
5666 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh else .ldrh,
56485667 3, 4 => .ldr,
56495668 else => unreachable,
56505669 };
56515670
56525671 const extra_offset = switch (abi_size) {
5653 1 => ty.isSignedInt(),
5672 1 => ty.isSignedInt(mod),
56545673 2 => true,
56555674 3, 4 => false,
56565675 else => unreachable,
......@@ -5659,7 +5678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56595678 if (extra_offset) {
56605679 const offset = if (off <= math.maxInt(u8)) blk: {
56615680 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, off));
5662 } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.usize), MCValue{ .immediate = off }));
5681 } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.usize, MCValue{ .immediate = off }));
56635682
56645683 _ = try self.addInst(.{
56655684 .tag = tag,
......@@ -5675,7 +5694,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56755694 } else {
56765695 const offset = if (off <= math.maxInt(u12)) blk: {
56775696 break :blk Instruction.Offset.imm(@intCast(u12, off));
5678 } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.usize), MCValue{ .immediate = off }), .none);
5697 } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.usize, MCValue{ .immediate = off }), .none);
56795698
56805699 _ = try self.addInst(.{
56815700 .tag = tag,
......@@ -5691,11 +5710,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56915710 }
56925711 },
56935712 .stack_argument_offset => |off| {
5694 const abi_size = ty.abiSize(self.target.*);
5713 const abi_size = ty.abiSize(mod);
56955714
56965715 const tag: Mir.Inst.Tag = switch (abi_size) {
5697 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,
5698 2 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
5716 1 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument,
5717 2 => if (ty.isSignedInt(mod)) Mir.Inst.Tag.ldrsh_stack_argument else .ldrh_stack_argument,
56995718 3, 4 => .ldr_stack_argument,
57005719 else => unreachable,
57015720 };
......@@ -5712,7 +5731,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
57125731}
57135732
57145733fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
5715 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5734 const mod = self.bin_file.options.module.?;
5735 const abi_size = @intCast(u32, ty.abiSize(mod));
57165736 switch (mcv) {
57175737 .dead => unreachable,
57185738 .none, .unreach => return,
......@@ -5732,7 +5752,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
57325752 1, 4 => {
57335753 const offset = if (math.cast(u12, stack_offset)) |imm| blk: {
57345754 break :blk Instruction.Offset.imm(imm);
5735 } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset }), .none);
5755 } else Instruction.Offset.reg(try self.copyToTmpRegister(Type.u32, MCValue{ .immediate = stack_offset }), .none);
57365756
57375757 const tag: Mir.Inst.Tag = switch (abi_size) {
57385758 1 => .strb,
......@@ -5752,7 +5772,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
57525772 2 => {
57535773 const offset = if (stack_offset <= math.maxInt(u8)) blk: {
57545774 break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, stack_offset));
5755 } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset }));
5775 } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.u32, MCValue{ .immediate = stack_offset }));
57565776
57575777 _ = try self.addInst(.{
57585778 .tag = .strh,
......@@ -5779,11 +5799,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
57795799 const reg = try self.copyToTmpRegister(ty, mcv);
57805800 return self.genSetStackArgument(ty, stack_offset, MCValue{ .register = reg });
57815801 } else {
5782 var ptr_ty_payload: Type.Payload.ElemType = .{
5783 .base = .{ .tag = .single_mut_pointer },
5784 .data = ty,
5785 };
5786 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
5802 const ptr_ty = try mod.singleMutPtrType(ty);
57875803
57885804 // TODO call extern memcpy
57895805 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, gp);
......@@ -5862,7 +5878,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
58625878 };
58635879 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
58645880
5865 const dest_ty = self.air.typeOfIndex(inst);
5881 const dest_ty = self.typeOfIndex(inst);
58665882 const dest = try self.allocRegOrMem(dest_ty, true, inst);
58675883 try self.setRegOrMem(dest_ty, dest, operand);
58685884 break :result dest;
......@@ -5871,16 +5887,17 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
58715887}
58725888
58735889fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
5890 const mod = self.bin_file.options.module.?;
58745891 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
58755892 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
5876 const ptr_ty = self.air.typeOf(ty_op.operand);
5893 const ptr_ty = self.typeOf(ty_op.operand);
58775894 const ptr = try self.resolveInst(ty_op.operand);
5878 const array_ty = ptr_ty.childType();
5879 const array_len = @intCast(u32, array_ty.arrayLen());
5895 const array_ty = ptr_ty.childType(mod);
5896 const array_len = @intCast(u32, array_ty.arrayLen(mod));
58805897
58815898 const stack_offset = try self.allocMem(8, 8, inst);
58825899 try self.genSetStack(ptr_ty, stack_offset, ptr);
5883 try self.genSetStack(Type.initTag(.usize), stack_offset - 4, .{ .immediate = array_len });
5900 try self.genSetStack(Type.usize, stack_offset - 4, .{ .immediate = array_len });
58845901 break :result MCValue{ .stack_offset = stack_offset };
58855902 };
58865903 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -5989,8 +6006,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
59896006}
59906007
59916008fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
5992 const vector_ty = self.air.typeOfIndex(inst);
5993 const len = vector_ty.vectorLen();
6009 const mod = self.bin_file.options.module.?;
6010 const vector_ty = self.typeOfIndex(inst);
6011 const len = vector_ty.vectorLen(mod);
59946012 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
59956013 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
59966014 const result: MCValue = res: {
......@@ -6038,9 +6056,10 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
60386056 const body = self.air.extra[extra.end..][0..extra.data.body_len];
60396057 const result: MCValue = result: {
60406058 const error_union_bind: ReadArg.Bind = .{ .inst = pl_op.operand };
6041 const error_union_ty = self.air.typeOf(pl_op.operand);
6042 const error_union_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
6043 const error_union_align = error_union_ty.abiAlignment(self.target.*);
6059 const error_union_ty = self.typeOf(pl_op.operand);
6060 const mod = self.bin_file.options.module.?;
6061 const error_union_size = @intCast(u32, error_union_ty.abiSize(mod));
6062 const error_union_align = error_union_ty.abiAlignment(mod);
60446063
60456064 // The error union will die in the body. However, we need the
60466065 // error union after the body in order to extract the payload
......@@ -6069,37 +6088,32 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
60696088}
60706089
60716090fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6072 // First section of indexes correspond to a set number of constant values.
6073 const ref_int = @enumToInt(inst);
6074 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
6075 const tv = Air.Inst.Ref.typed_value_map[ref_int];
6076 if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) {
6077 return MCValue{ .none = {} };
6078 }
6079 return self.genTypedValue(tv);
6080 }
6091 const mod = self.bin_file.options.module.?;
60816092
60826093 // If the type has no codegen bits, no need to store it.
6083 const inst_ty = self.air.typeOf(inst);
6084 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())
6094 const inst_ty = self.typeOf(inst);
6095 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod))
60856096 return MCValue{ .none = {} };
60866097
6087 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
6098 const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
6099 .ty = inst_ty,
6100 .val = (try self.air.value(inst, mod)).?,
6101 });
6102
60886103 switch (self.air.instructions.items(.tag)[inst_index]) {
6089 .constant => {
6104 .interned => {
60906105 // Constants have static lifetimes, so they are always memoized in the outer most table.
60916106 const branch = &self.branch_stack.items[0];
60926107 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
60936108 if (!gop.found_existing) {
6094 const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;
6109 const interned = self.air.instructions.items(.data)[inst_index].interned;
60956110 gop.value_ptr.* = try self.genTypedValue(.{
60966111 .ty = inst_ty,
6097 .val = self.air.values[ty_pl.payload],
6112 .val = interned.toValue(),
60986113 });
60996114 }
61006115 return gop.value_ptr.*;
61016116 },
6102 .const_ty => unreachable,
61036117 else => return self.getResolvedInstValue(inst_index),
61046118 }
61056119}
......@@ -6152,12 +6166,11 @@ const CallMCValues = struct {
61526166
61536167/// Caller must call `CallMCValues.deinit`.
61546168fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6155 const cc = fn_ty.fnCallingConvention();
6156 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
6157 defer self.gpa.free(param_types);
6158 fn_ty.fnParamTypes(param_types);
6169 const mod = self.bin_file.options.module.?;
6170 const fn_info = mod.typeToFunc(fn_ty).?;
6171 const cc = fn_info.cc;
61596172 var result: CallMCValues = .{
6160 .args = try self.gpa.alloc(MCValue, param_types.len),
6173 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
61616174 // These undefined values must be populated before returning from this function.
61626175 .return_value = undefined,
61636176 .stack_byte_count = undefined,
......@@ -6165,7 +6178,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61656178 };
61666179 errdefer self.gpa.free(result.args);
61676180
6168 const ret_ty = fn_ty.fnReturnType();
6181 const ret_ty = fn_ty.fnReturnType(mod);
61696182
61706183 switch (cc) {
61716184 .Naked => {
......@@ -6180,12 +6193,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61806193 var ncrn: usize = 0; // Next Core Register Number
61816194 var nsaa: u32 = 0; // Next stacked argument address
61826195
6183 if (ret_ty.zigTypeTag() == .NoReturn) {
6196 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
61846197 result.return_value = .{ .unreach = {} };
6185 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
6198 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
61866199 result.return_value = .{ .none = {} };
61876200 } else {
6188 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
6201 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
61896202 // TODO handle cases where multiple registers are used
61906203 if (ret_ty_size <= 4) {
61916204 result.return_value = .{ .register = c_abi_int_return_regs[0] };
......@@ -6199,11 +6212,11 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
61996212 }
62006213 }
62016214
6202 for (param_types, 0..) |ty, i| {
6203 if (ty.abiAlignment(self.target.*) == 8)
6215 for (fn_info.param_types, 0..) |ty, i| {
6216 if (ty.toType().abiAlignment(mod) == 8)
62046217 ncrn = std.mem.alignForwardGeneric(usize, ncrn, 2);
62056218
6206 const param_size = @intCast(u32, ty.abiSize(self.target.*));
6219 const param_size = @intCast(u32, ty.toType().abiSize(mod));
62076220 if (std.math.divCeil(u32, param_size, 4) catch unreachable <= 4 - ncrn) {
62086221 if (param_size <= 4) {
62096222 result.args[i] = .{ .register = c_abi_int_param_regs[ncrn] };
......@@ -6215,7 +6228,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62156228 return self.fail("TODO MCValues split between registers and stack", .{});
62166229 } else {
62176230 ncrn = 4;
6218 if (ty.abiAlignment(self.target.*) == 8)
6231 if (ty.toType().abiAlignment(mod) == 8)
62196232 nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8);
62206233
62216234 result.args[i] = .{ .stack_argument_offset = nsaa };
......@@ -6227,14 +6240,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62276240 result.stack_align = 8;
62286241 },
62296242 .Unspecified => {
6230 if (ret_ty.zigTypeTag() == .NoReturn) {
6243 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
62316244 result.return_value = .{ .unreach = {} };
6232 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
6245 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) {
62336246 result.return_value = .{ .none = {} };
62346247 } else {
6235 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
6248 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
62366249 if (ret_ty_size == 0) {
6237 assert(ret_ty.isError());
6250 assert(ret_ty.isError(mod));
62386251 result.return_value = .{ .immediate = 0 };
62396252 } else if (ret_ty_size <= 4) {
62406253 result.return_value = .{ .register = .r0 };
......@@ -6249,10 +6262,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
62496262
62506263 var stack_offset: u32 = 0;
62516264
6252 for (param_types, 0..) |ty, i| {
6253 if (ty.abiSize(self.target.*) > 0) {
6254 const param_size = @intCast(u32, ty.abiSize(self.target.*));
6255 const param_alignment = ty.abiAlignment(self.target.*);
6265 for (fn_info.param_types, 0..) |ty, i| {
6266 if (ty.toType().abiSize(mod) > 0) {
6267 const param_size = @intCast(u32, ty.toType().abiSize(mod));
6268 const param_alignment = ty.toType().abiAlignment(mod);
62566269
62576270 stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, param_alignment);
62586271 result.args[i] = .{ .stack_argument_offset = stack_offset };
......@@ -6301,3 +6314,13 @@ fn parseRegName(name: []const u8) ?Register {
63016314 }
63026315 return std.meta.stringToEnum(Register, name);
63036316}
6317
6318fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
6319 const mod = self.bin_file.options.module.?;
6320 return self.air.typeOf(inst, &mod.intern_pool);
6321}
6322
6323fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
6324 const mod = self.bin_file.options.module.?;
6325 return self.air.typeOfIndex(inst, &mod.intern_pool);
6326}
src/arch/arm/abi.zig+30-27
......@@ -1,8 +1,10 @@
11const std = @import("std");
2const assert = std.debug.assert;
23const bits = @import("bits.zig");
34const Register = bits.Register;
45const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
56const Type = @import("../../type.zig").Type;
7const Module = @import("../../Module.zig");
68
79pub const Class = union(enum) {
810 memory,
......@@ -22,28 +24,28 @@ pub const Class = union(enum) {
2224
2325pub const Context = enum { ret, arg };
2426
25pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
26 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime());
27pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class {
28 assert(ty.hasRuntimeBitsIgnoreComptime(mod));
2729
2830 var maybe_float_bits: ?u16 = null;
2931 const max_byval_size = 512;
30 switch (ty.zigTypeTag()) {
32 switch (ty.zigTypeTag(mod)) {
3133 .Struct => {
32 const bit_size = ty.bitSize(target);
33 if (ty.containerLayout() == .Packed) {
34 const bit_size = ty.bitSize(mod);
35 if (ty.containerLayout(mod) == .Packed) {
3436 if (bit_size > 64) return .memory;
3537 return .byval;
3638 }
3739 if (bit_size > max_byval_size) return .memory;
38 const float_count = countFloats(ty, target, &maybe_float_bits);
40 const float_count = countFloats(ty, mod, &maybe_float_bits);
3941 if (float_count <= byval_float_count) return .byval;
4042
41 const fields = ty.structFieldCount();
43 const fields = ty.structFieldCount(mod);
4244 var i: u32 = 0;
4345 while (i < fields) : (i += 1) {
44 const field_ty = ty.structFieldType(i);
45 const field_alignment = ty.structFieldAlign(i, target);
46 const field_size = field_ty.bitSize(target);
46 const field_ty = ty.structFieldType(i, mod);
47 const field_alignment = ty.structFieldAlign(i, mod);
48 const field_size = field_ty.bitSize(mod);
4749 if (field_size > 32 or field_alignment > 32) {
4850 return Class.arrSize(bit_size, 64);
4951 }
......@@ -51,17 +53,17 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
5153 return Class.arrSize(bit_size, 32);
5254 },
5355 .Union => {
54 const bit_size = ty.bitSize(target);
55 if (ty.containerLayout() == .Packed) {
56 const bit_size = ty.bitSize(mod);
57 if (ty.containerLayout(mod) == .Packed) {
5658 if (bit_size > 64) return .memory;
5759 return .byval;
5860 }
5961 if (bit_size > max_byval_size) return .memory;
60 const float_count = countFloats(ty, target, &maybe_float_bits);
62 const float_count = countFloats(ty, mod, &maybe_float_bits);
6163 if (float_count <= byval_float_count) return .byval;
6264
63 for (ty.unionFields().values()) |field| {
64 if (field.ty.bitSize(target) > 32 or field.normalAlignment(target) > 32) {
65 for (ty.unionFields(mod).values()) |field| {
66 if (field.ty.bitSize(mod) > 32 or field.normalAlignment(mod) > 32) {
6567 return Class.arrSize(bit_size, 64);
6668 }
6769 }
......@@ -71,28 +73,28 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
7173 .Int => {
7274 // TODO this is incorrect for _BitInt(128) but implementing
7375 // this correctly makes implementing compiler-rt impossible.
74 // const bit_size = ty.bitSize(target);
76 // const bit_size = ty.bitSize(mod);
7577 // if (bit_size > 64) return .memory;
7678 return .byval;
7779 },
7880 .Enum, .ErrorSet => {
79 const bit_size = ty.bitSize(target);
81 const bit_size = ty.bitSize(mod);
8082 if (bit_size > 64) return .memory;
8183 return .byval;
8284 },
8385 .Vector => {
84 const bit_size = ty.bitSize(target);
86 const bit_size = ty.bitSize(mod);
8587 // TODO is this controlled by a cpu feature?
8688 if (ctx == .ret and bit_size > 128) return .memory;
8789 if (bit_size > 512) return .memory;
8890 return .byval;
8991 },
9092 .Optional => {
91 std.debug.assert(ty.isPtrLikeOptional());
93 assert(ty.isPtrLikeOptional(mod));
9294 return .byval;
9395 },
9496 .Pointer => {
95 std.debug.assert(!ty.isSlice());
97 assert(!ty.isSlice(mod));
9698 return .byval;
9799 },
98100 .ErrorUnion,
......@@ -114,14 +116,15 @@ pub fn classifyType(ty: Type, target: std.Target, ctx: Context) Class {
114116}
115117
116118const byval_float_count = 4;
117fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
119fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 {
120 const target = mod.getTarget();
118121 const invalid = std.math.maxInt(u32);
119 switch (ty.zigTypeTag()) {
122 switch (ty.zigTypeTag(mod)) {
120123 .Union => {
121 const fields = ty.unionFields();
124 const fields = ty.unionFields(mod);
122125 var max_count: u32 = 0;
123126 for (fields.values()) |field| {
124 const field_count = countFloats(field.ty, target, maybe_float_bits);
127 const field_count = countFloats(field.ty, mod, maybe_float_bits);
125128 if (field_count == invalid) return invalid;
126129 if (field_count > max_count) max_count = field_count;
127130 if (max_count > byval_float_count) return invalid;
......@@ -129,12 +132,12 @@ fn countFloats(ty: Type, target: std.Target, maybe_float_bits: *?u16) u32 {
129132 return max_count;
130133 },
131134 .Struct => {
132 const fields_len = ty.structFieldCount();
135 const fields_len = ty.structFieldCount(mod);
133136 var count: u32 = 0;
134137 var i: u32 = 0;
135138 while (i < fields_len) : (i += 1) {
136 const field_ty = ty.structFieldType(i);
137 const field_count = countFloats(field_ty, target, maybe_float_bits);
139 const field_ty = ty.structFieldType(i, mod);
140 const field_count = countFloats(field_ty, mod, maybe_float_bits);
138141 if (field_count == invalid) return invalid;
139142 count += field_count;
140143 if (count > byval_float_count) return invalid;
src/arch/riscv64/CodeGen.zig+108-95
......@@ -217,7 +217,7 @@ const Self = @This();
217217pub fn generate(
218218 bin_file: *link.File,
219219 src_loc: Module.SrcLoc,
220 module_fn: *Module.Fn,
220 module_fn_index: Module.Fn.Index,
221221 air: Air,
222222 liveness: Liveness,
223223 code: *std.ArrayList(u8),
......@@ -228,6 +228,7 @@ pub fn generate(
228228 }
229229
230230 const mod = bin_file.options.module.?;
231 const module_fn = mod.funcPtr(module_fn_index);
231232 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
232233 assert(fn_owner_decl.has_tv);
233234 const fn_type = fn_owner_decl.ty;
......@@ -347,7 +348,8 @@ pub fn addExtraAssumeCapacity(self: *Self, extra: anytype) u32 {
347348}
348349
349350fn gen(self: *Self) !void {
350 const cc = self.fn_type.fnCallingConvention();
351 const mod = self.bin_file.options.module.?;
352 const cc = self.fn_type.fnCallingConvention(mod);
351353 if (cc != .Naked) {
352354 // TODO Finish function prologue and epilogue for riscv64.
353355
......@@ -470,13 +472,14 @@ fn gen(self: *Self) !void {
470472}
471473
472474fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
475 const mod = self.bin_file.options.module.?;
476 const ip = &mod.intern_pool;
473477 const air_tags = self.air.instructions.items(.tag);
474478
475479 for (body) |inst| {
476480 // TODO: remove now-redundant isUnused calls from AIR handler functions
477 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
481 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
478482 continue;
479 }
480483
481484 const old_air_bookkeeping = self.air_bookkeeping;
482485 try self.ensureProcessDeathCapacity(Liveness.bpi);
......@@ -656,8 +659,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
656659 .ptr_elem_val => try self.airPtrElemVal(inst),
657660 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
658661
659 .constant => unreachable, // excluded from function bodies
660 .const_ty => unreachable, // excluded from function bodies
662 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
661663 .unreach => self.finishAirBookkeeping(),
662664
663665 .optional_payload => try self.airOptionalPayload(inst),
......@@ -727,8 +729,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
727729
728730/// Asserts there is already capacity to insert into top branch inst_table.
729731fn processDeath(self: *Self, inst: Air.Inst.Index) void {
730 const air_tags = self.air.instructions.items(.tag);
731 if (air_tags[inst] == .constant) return; // Constants are immortal.
732 assert(self.air.instructions.items(.tag)[inst] != .interned);
732733 // When editing this function, note that the logic must synchronize with `reuseOperand`.
733734 const prev_value = self.getResolvedInstValue(inst);
734735 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -755,8 +756,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
755756 tomb_bits >>= 1;
756757 if (!dies) continue;
757758 const op_int = @enumToInt(op);
758 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;
759 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
759 if (op_int < Air.ref_start_index) continue;
760 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
760761 self.processDeath(op_index);
761762 }
762763 const is_used = @truncate(u1, tomb_bits) == 0;
......@@ -804,23 +805,23 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
804805
805806/// Use a pointer instruction as the basis for allocating stack memory.
806807fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
807 const elem_ty = self.air.typeOfIndex(inst).elemType();
808 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
809 const mod = self.bin_file.options.module.?;
808 const mod = self.bin_file.options.module.?;
809 const elem_ty = self.typeOfIndex(inst).childType(mod);
810 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
810811 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
811812 };
812813 // TODO swap this for inst.ty.ptrAlign
813 const abi_align = elem_ty.abiAlignment(self.target.*);
814 const abi_align = elem_ty.abiAlignment(mod);
814815 return self.allocMem(inst, abi_size, abi_align);
815816}
816817
817818fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
818 const elem_ty = self.air.typeOfIndex(inst);
819 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
820 const mod = self.bin_file.options.module.?;
819 const mod = self.bin_file.options.module.?;
820 const elem_ty = self.typeOfIndex(inst);
821 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
821822 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
822823 };
823 const abi_align = elem_ty.abiAlignment(self.target.*);
824 const abi_align = elem_ty.abiAlignment(mod);
824825 if (abi_align > self.stack_align)
825826 self.stack_align = abi_align;
826827
......@@ -845,7 +846,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
845846 assert(reg == reg_mcv.register);
846847 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
847848 try branch.inst_table.put(self.gpa, inst, stack_mcv);
848 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
849 try self.genSetStack(self.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
849850}
850851
851852/// Copies a value to a register without tracking the register. The register is not considered
......@@ -862,7 +863,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
862863/// This can have a side effect of spilling instructions to the stack to free up a register.
863864fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
864865 const reg = try self.register_manager.allocReg(reg_owner, gp);
865 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
866 try self.genSetReg(self.typeOfIndex(reg_owner), reg, mcv);
866867 return MCValue{ .register = reg };
867868}
868869
......@@ -893,10 +894,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
893894 if (self.liveness.isUnused(inst))
894895 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
895896
896 const operand_ty = self.air.typeOf(ty_op.operand);
897 const mod = self.bin_file.options.module.?;
898 const operand_ty = self.typeOf(ty_op.operand);
897899 const operand = try self.resolveInst(ty_op.operand);
898 const info_a = operand_ty.intInfo(self.target.*);
899 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);
900 const info_a = operand_ty.intInfo(mod);
901 const info_b = self.typeOfIndex(inst).intInfo(mod);
900902 if (info_a.signedness != info_b.signedness)
901903 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
902904
......@@ -1068,18 +1070,18 @@ fn binOp(
10681070 lhs_ty: Type,
10691071 rhs_ty: Type,
10701072) InnerError!MCValue {
1073 const mod = self.bin_file.options.module.?;
10711074 switch (tag) {
10721075 // Arithmetic operations on integers and floats
10731076 .add,
10741077 .sub,
10751078 => {
1076 switch (lhs_ty.zigTypeTag()) {
1079 switch (lhs_ty.zigTypeTag(mod)) {
10771080 .Float => return self.fail("TODO binary operations on floats", .{}),
10781081 .Vector => return self.fail("TODO binary operations on vectors", .{}),
10791082 .Int => {
1080 const mod = self.bin_file.options.module.?;
10811083 assert(lhs_ty.eql(rhs_ty, mod));
1082 const int_info = lhs_ty.intInfo(self.target.*);
1084 const int_info = lhs_ty.intInfo(mod);
10831085 if (int_info.bits <= 64) {
10841086 // TODO immediate operands
10851087 return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
......@@ -1093,14 +1095,14 @@ fn binOp(
10931095 .ptr_add,
10941096 .ptr_sub,
10951097 => {
1096 switch (lhs_ty.zigTypeTag()) {
1098 switch (lhs_ty.zigTypeTag(mod)) {
10971099 .Pointer => {
10981100 const ptr_ty = lhs_ty;
1099 const elem_ty = switch (ptr_ty.ptrSize()) {
1100 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
1101 else => ptr_ty.childType(),
1101 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
1102 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
1103 else => ptr_ty.childType(mod),
11021104 };
1103 const elem_size = elem_ty.abiSize(self.target.*);
1105 const elem_size = elem_ty.abiSize(mod);
11041106
11051107 if (elem_size == 1) {
11061108 const base_tag: Air.Inst.Tag = switch (tag) {
......@@ -1125,8 +1127,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
11251127 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
11261128 const lhs = try self.resolveInst(bin_op.lhs);
11271129 const rhs = try self.resolveInst(bin_op.rhs);
1128 const lhs_ty = self.air.typeOf(bin_op.lhs);
1129 const rhs_ty = self.air.typeOf(bin_op.rhs);
1130 const lhs_ty = self.typeOf(bin_op.lhs);
1131 const rhs_ty = self.typeOf(bin_op.rhs);
11301132
11311133 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
11321134 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -1137,8 +1139,8 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
11371139 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
11381140 const lhs = try self.resolveInst(bin_op.lhs);
11391141 const rhs = try self.resolveInst(bin_op.rhs);
1140 const lhs_ty = self.air.typeOf(bin_op.lhs);
1141 const rhs_ty = self.air.typeOf(bin_op.rhs);
1142 const lhs_ty = self.typeOf(bin_op.lhs);
1143 const rhs_ty = self.typeOf(bin_op.rhs);
11421144
11431145 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
11441146 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -1331,10 +1333,11 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
13311333fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
13321334 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
13331335 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1334 const optional_ty = self.air.typeOfIndex(inst);
1336 const mod = self.bin_file.options.module.?;
1337 const optional_ty = self.typeOfIndex(inst);
13351338
13361339 // Optional with a zero-bit payload type is just a boolean true
1337 if (optional_ty.abiSize(self.target.*) == 1)
1340 if (optional_ty.abiSize(mod) == 1)
13381341 break :result MCValue{ .immediate = 1 };
13391342
13401343 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});
......@@ -1498,7 +1501,8 @@ fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_ind
14981501}
14991502
15001503fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
1501 const elem_ty = ptr_ty.elemType();
1504 const mod = self.bin_file.options.module.?;
1505 const elem_ty = ptr_ty.childType(mod);
15021506 switch (ptr) {
15031507 .none => unreachable,
15041508 .undef => unreachable,
......@@ -1523,14 +1527,15 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
15231527}
15241528
15251529fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1530 const mod = self.bin_file.options.module.?;
15261531 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1527 const elem_ty = self.air.typeOfIndex(inst);
1532 const elem_ty = self.typeOfIndex(inst);
15281533 const result: MCValue = result: {
1529 if (!elem_ty.hasRuntimeBits())
1534 if (!elem_ty.hasRuntimeBits(mod))
15301535 break :result MCValue.none;
15311536
15321537 const ptr = try self.resolveInst(ty_op.operand);
1533 const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
1538 const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(mod);
15341539 if (self.liveness.isUnused(inst) and !is_volatile)
15351540 break :result MCValue.dead;
15361541
......@@ -1542,7 +1547,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
15421547 break :blk try self.allocRegOrMem(inst, true);
15431548 }
15441549 };
1545 try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand));
1550 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
15461551 break :result dst_mcv;
15471552 };
15481553 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -1583,8 +1588,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
15831588 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
15841589 const ptr = try self.resolveInst(bin_op.lhs);
15851590 const value = try self.resolveInst(bin_op.rhs);
1586 const ptr_ty = self.air.typeOf(bin_op.lhs);
1587 const value_ty = self.air.typeOf(bin_op.rhs);
1591 const ptr_ty = self.typeOf(bin_op.lhs);
1592 const value_ty = self.typeOf(bin_op.rhs);
15881593
15891594 try self.store(ptr, value, ptr_ty, value_ty);
15901595
......@@ -1644,7 +1649,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
16441649 const arg_index = self.arg_index;
16451650 self.arg_index += 1;
16461651
1647 const ty = self.air.typeOfIndex(inst);
1652 const ty = self.typeOfIndex(inst);
16481653 _ = ty;
16491654
16501655 const result = self.args[arg_index];
......@@ -1698,9 +1703,10 @@ fn airFence(self: *Self) !void {
16981703}
16991704
17001705fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
1706 const mod = self.bin_file.options.module.?;
17011707 if (modifier == .always_tail) return self.fail("TODO implement tail calls for riscv64", .{});
17021708 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1703 const fn_ty = self.air.typeOf(pl_op.operand);
1709 const fn_ty = self.typeOf(pl_op.operand);
17041710 const callee = pl_op.operand;
17051711 const extra = self.air.extraData(Air.Call, pl_op.payload);
17061712 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
......@@ -1713,7 +1719,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17131719 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
17141720 for (info.args, 0..) |mc_arg, arg_i| {
17151721 const arg = args[arg_i];
1716 const arg_ty = self.air.typeOf(arg);
1722 const arg_ty = self.typeOf(arg);
17171723 const arg_mcv = try self.resolveInst(args[arg_i]);
17181724
17191725 switch (mc_arg) {
......@@ -1736,14 +1742,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17361742 }
17371743 }
17381744
1739 if (self.air.value(callee)) |func_value| {
1740 if (func_value.castTag(.function)) |func_payload| {
1741 const func = func_payload.data;
1745 if (try self.air.value(callee, mod)) |func_value| {
1746 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
17421747 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
17431748 const atom = elf_file.getAtom(atom_index);
17441749 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
17451750 const got_addr = @intCast(u32, atom.getOffsetTableAddress(elf_file));
1746 try self.genSetReg(Type.initTag(.usize), .ra, .{ .memory = got_addr });
1751 try self.genSetReg(Type.usize, .ra, .{ .memory = got_addr });
17471752 _ = try self.addInst(.{
17481753 .tag = .jalr,
17491754 .data = .{ .i_type = .{
......@@ -1752,7 +1757,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17521757 .imm12 = 0,
17531758 } },
17541759 });
1755 } else if (func_value.castTag(.extern_fn)) |_| {
1760 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
17561761 return self.fail("TODO implement calling extern functions", .{});
17571762 } else {
17581763 return self.fail("TODO implement calling bitcasted functions", .{});
......@@ -1796,7 +1801,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
17961801}
17971802
17981803fn ret(self: *Self, mcv: MCValue) !void {
1799 const ret_ty = self.fn_type.fnReturnType();
1804 const mod = self.bin_file.options.module.?;
1805 const ret_ty = self.fn_type.fnReturnType(mod);
18001806 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
18011807 // Just add space for an instruction, patch this later
18021808 const index = try self.addInst(.{
......@@ -1825,10 +1831,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
18251831 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
18261832 if (self.liveness.isUnused(inst))
18271833 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
1828 const ty = self.air.typeOf(bin_op.lhs);
1834 const ty = self.typeOf(bin_op.lhs);
18291835 const mod = self.bin_file.options.module.?;
1830 assert(ty.eql(self.air.typeOf(bin_op.rhs), mod));
1831 if (ty.zigTypeTag() == .ErrorSet)
1836 assert(ty.eql(self.typeOf(bin_op.rhs), mod));
1837 if (ty.zigTypeTag(mod) == .ErrorSet)
18321838 return self.fail("TODO implement cmp for errors", .{});
18331839
18341840 const lhs = try self.resolveInst(bin_op.lhs);
......@@ -1869,8 +1875,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
18691875}
18701876
18711877fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1872 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1873 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
1878 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1879 const mod = self.bin_file.options.module.?;
1880 const function = mod.funcPtr(ty_fn.func);
18741881 // TODO emit debug info for function change
18751882 _ = function;
18761883 return self.finishAir(inst, .dead, .{ .none, .none, .none });
......@@ -1946,7 +1953,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
19461953 break :blk try self.allocRegOrMem(inst, true);
19471954 }
19481955 };
1949 try self.load(operand, operand_ptr, self.air.typeOf(un_op));
1956 try self.load(operand, operand_ptr, self.typeOf(un_op));
19501957 break :result try self.isNull(operand);
19511958 };
19521959 return self.finishAir(inst, result, .{ un_op, .none, .none });
......@@ -1973,7 +1980,7 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
19731980 break :blk try self.allocRegOrMem(inst, true);
19741981 }
19751982 };
1976 try self.load(operand, operand_ptr, self.air.typeOf(un_op));
1983 try self.load(operand, operand_ptr, self.typeOf(un_op));
19771984 break :result try self.isNonNull(operand);
19781985 };
19791986 return self.finishAir(inst, result, .{ un_op, .none, .none });
......@@ -2000,7 +2007,7 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
20002007 break :blk try self.allocRegOrMem(inst, true);
20012008 }
20022009 };
2003 try self.load(operand, operand_ptr, self.air.typeOf(un_op));
2010 try self.load(operand, operand_ptr, self.typeOf(un_op));
20042011 break :result try self.isErr(operand);
20052012 };
20062013 return self.finishAir(inst, result, .{ un_op, .none, .none });
......@@ -2027,7 +2034,7 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
20272034 break :blk try self.allocRegOrMem(inst, true);
20282035 }
20292036 };
2030 try self.load(operand, operand_ptr, self.air.typeOf(un_op));
2037 try self.load(operand, operand_ptr, self.typeOf(un_op));
20312038 break :result try self.isNonErr(operand);
20322039 };
20332040 return self.finishAir(inst, result, .{ un_op, .none, .none });
......@@ -2107,13 +2114,14 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void {
21072114fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
21082115 const block_data = self.blocks.getPtr(block).?;
21092116
2110 if (self.air.typeOf(operand).hasRuntimeBits()) {
2117 const mod = self.bin_file.options.module.?;
2118 if (self.typeOf(operand).hasRuntimeBits(mod)) {
21112119 const operand_mcv = try self.resolveInst(operand);
21122120 const block_mcv = block_data.mcv;
21132121 if (block_mcv == .none) {
21142122 block_data.mcv = operand_mcv;
21152123 } else {
2116 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
2124 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
21172125 }
21182126 }
21192127 return self.brVoid(block);
......@@ -2176,7 +2184,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
21762184
21772185 const arg_mcv = try self.resolveInst(input);
21782186 try self.register_manager.getReg(reg, null);
2179 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
2187 try self.genSetReg(self.typeOf(input), reg, arg_mcv);
21802188 }
21812189
21822190 {
......@@ -2372,7 +2380,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
23722380 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
23732381
23742382 const dest = try self.allocRegOrMem(inst, true);
2375 try self.setRegOrMem(self.air.typeOfIndex(inst), dest, operand);
2383 try self.setRegOrMem(self.typeOfIndex(inst), dest, operand);
23762384 break :result dest;
23772385 };
23782386 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -2489,8 +2497,9 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
24892497}
24902498
24912499fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
2492 const vector_ty = self.air.typeOfIndex(inst);
2493 const len = vector_ty.vectorLen();
2500 const mod = self.bin_file.options.module.?;
2501 const vector_ty = self.typeOfIndex(inst);
2502 const len = vector_ty.vectorLen(mod);
24942503 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
24952504 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
24962505 const result: MCValue = res: {
......@@ -2533,37 +2542,32 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
25332542}
25342543
25352544fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
2536 // First section of indexes correspond to a set number of constant values.
2537 const ref_int = @enumToInt(inst);
2538 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
2539 const tv = Air.Inst.Ref.typed_value_map[ref_int];
2540 if (!tv.ty.hasRuntimeBits()) {
2541 return MCValue{ .none = {} };
2542 }
2543 return self.genTypedValue(tv);
2544 }
2545 const mod = self.bin_file.options.module.?;
25452546
25462547 // If the type has no codegen bits, no need to store it.
2547 const inst_ty = self.air.typeOf(inst);
2548 if (!inst_ty.hasRuntimeBits())
2548 const inst_ty = self.typeOf(inst);
2549 if (!inst_ty.hasRuntimeBits(mod))
25492550 return MCValue{ .none = {} };
25502551
2551 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
2552 const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
2553 .ty = inst_ty,
2554 .val = (try self.air.value(inst, mod)).?,
2555 });
2556
25522557 switch (self.air.instructions.items(.tag)[inst_index]) {
2553 .constant => {
2558 .interned => {
25542559 // Constants have static lifetimes, so they are always memoized in the outer most table.
25552560 const branch = &self.branch_stack.items[0];
25562561 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
25572562 if (!gop.found_existing) {
2558 const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;
2563 const interned = self.air.instructions.items(.data)[inst_index].interned;
25592564 gop.value_ptr.* = try self.genTypedValue(.{
25602565 .ty = inst_ty,
2561 .val = self.air.values[ty_pl.payload],
2566 .val = interned.toValue(),
25622567 });
25632568 }
25642569 return gop.value_ptr.*;
25652570 },
2566 .const_ty => unreachable,
25672571 else => return self.getResolvedInstValue(inst_index),
25682572 }
25692573}
......@@ -2616,12 +2620,11 @@ const CallMCValues = struct {
26162620
26172621/// Caller must call `CallMCValues.deinit`.
26182622fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
2619 const cc = fn_ty.fnCallingConvention();
2620 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
2621 defer self.gpa.free(param_types);
2622 fn_ty.fnParamTypes(param_types);
2623 const mod = self.bin_file.options.module.?;
2624 const fn_info = mod.typeToFunc(fn_ty).?;
2625 const cc = fn_info.cc;
26232626 var result: CallMCValues = .{
2624 .args = try self.gpa.alloc(MCValue, param_types.len),
2627 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
26252628 // These undefined values must be populated before returning from this function.
26262629 .return_value = undefined,
26272630 .stack_byte_count = undefined,
......@@ -2629,7 +2632,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26292632 };
26302633 errdefer self.gpa.free(result.args);
26312634
2632 const ret_ty = fn_ty.fnReturnType();
2635 const ret_ty = fn_ty.fnReturnType(mod);
26332636
26342637 switch (cc) {
26352638 .Naked => {
......@@ -2649,8 +2652,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26492652 var next_stack_offset: u32 = 0;
26502653 const argument_registers = [_]Register{ .a0, .a1, .a2, .a3, .a4, .a5, .a6, .a7 };
26512654
2652 for (param_types, 0..) |ty, i| {
2653 const param_size = @intCast(u32, ty.abiSize(self.target.*));
2655 for (fn_info.param_types, 0..) |ty, i| {
2656 const param_size = @intCast(u32, ty.toType().abiSize(mod));
26542657 if (param_size <= 8) {
26552658 if (next_register < argument_registers.len) {
26562659 result.args[i] = .{ .register = argument_registers[next_register] };
......@@ -2680,14 +2683,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
26802683 else => return self.fail("TODO implement function parameters for {} on riscv64", .{cc}),
26812684 }
26822685
2683 if (ret_ty.zigTypeTag() == .NoReturn) {
2686 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
26842687 result.return_value = .{ .unreach = {} };
2685 } else if (!ret_ty.hasRuntimeBits()) {
2688 } else if (!ret_ty.hasRuntimeBits(mod)) {
26862689 result.return_value = .{ .none = {} };
26872690 } else switch (cc) {
26882691 .Naked => unreachable,
26892692 .Unspecified, .C => {
2690 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
2693 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
26912694 if (ret_ty_size <= 8) {
26922695 result.return_value = .{ .register = .a0 };
26932696 } else if (ret_ty_size <= 16) {
......@@ -2731,3 +2734,13 @@ fn parseRegName(name: []const u8) ?Register {
27312734 }
27322735 return std.meta.stringToEnum(Register, name);
27332736}
2737
2738fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
2739 const mod = self.bin_file.options.module.?;
2740 return self.air.typeOf(inst, &mod.intern_pool);
2741}
2742
2743fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
2744 const mod = self.bin_file.options.module.?;
2745 return self.air.typeOfIndex(inst, &mod.intern_pool);
2746}
src/arch/riscv64/abi.zig+13-11
......@@ -3,17 +3,19 @@ const bits = @import("bits.zig");
33const Register = bits.Register;
44const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
55const Type = @import("../../type.zig").Type;
6const Module = @import("../../Module.zig");
67
78pub const Class = enum { memory, byval, integer, double_integer };
89
9pub fn classifyType(ty: Type, target: std.Target) Class {
10 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime());
10pub fn classifyType(ty: Type, mod: *Module) Class {
11 const target = mod.getTarget();
12 std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1113
1214 const max_byval_size = target.ptrBitWidth() * 2;
13 switch (ty.zigTypeTag()) {
15 switch (ty.zigTypeTag(mod)) {
1416 .Struct => {
15 const bit_size = ty.bitSize(target);
16 if (ty.containerLayout() == .Packed) {
17 const bit_size = ty.bitSize(mod);
18 if (ty.containerLayout(mod) == .Packed) {
1719 if (bit_size > max_byval_size) return .memory;
1820 return .byval;
1921 }
......@@ -23,8 +25,8 @@ pub fn classifyType(ty: Type, target: std.Target) Class {
2325 return .integer;
2426 },
2527 .Union => {
26 const bit_size = ty.bitSize(target);
27 if (ty.containerLayout() == .Packed) {
28 const bit_size = ty.bitSize(mod);
29 if (ty.containerLayout(mod) == .Packed) {
2830 if (bit_size > max_byval_size) return .memory;
2931 return .byval;
3032 }
......@@ -36,21 +38,21 @@ pub fn classifyType(ty: Type, target: std.Target) Class {
3638 .Bool => return .integer,
3739 .Float => return .byval,
3840 .Int, .Enum, .ErrorSet => {
39 const bit_size = ty.bitSize(target);
41 const bit_size = ty.bitSize(mod);
4042 if (bit_size > max_byval_size) return .memory;
4143 return .byval;
4244 },
4345 .Vector => {
44 const bit_size = ty.bitSize(target);
46 const bit_size = ty.bitSize(mod);
4547 if (bit_size > max_byval_size) return .memory;
4648 return .integer;
4749 },
4850 .Optional => {
49 std.debug.assert(ty.isPtrLikeOptional());
51 std.debug.assert(ty.isPtrLikeOptional(mod));
5052 return .byval;
5153 },
5254 .Pointer => {
53 std.debug.assert(!ty.isSlice());
55 std.debug.assert(!ty.isSlice(mod));
5456 return .byval;
5557 },
5658 .ErrorUnion,
src/arch/sparc64/CodeGen.zig+244-222
......@@ -260,7 +260,7 @@ const BigTomb = struct {
260260pub fn generate(
261261 bin_file: *link.File,
262262 src_loc: Module.SrcLoc,
263 module_fn: *Module.Fn,
263 module_fn_index: Module.Fn.Index,
264264 air: Air,
265265 liveness: Liveness,
266266 code: *std.ArrayList(u8),
......@@ -271,12 +271,11 @@ pub fn generate(
271271 }
272272
273273 const mod = bin_file.options.module.?;
274 const module_fn = mod.funcPtr(module_fn_index);
274275 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
275276 assert(fn_owner_decl.has_tv);
276277 const fn_type = fn_owner_decl.ty;
277278
278 log.debug("fn {s}", .{fn_owner_decl.name});
279
280279 var branch_stack = std.ArrayList(Branch).init(bin_file.allocator);
281280 defer {
282281 assert(branch_stack.items.len == 1);
......@@ -363,7 +362,8 @@ pub fn generate(
363362}
364363
365364fn gen(self: *Self) !void {
366 const cc = self.fn_type.fnCallingConvention();
365 const mod = self.bin_file.options.module.?;
366 const cc = self.fn_type.fnCallingConvention(mod);
367367 if (cc != .Naked) {
368368 // TODO Finish function prologue and epilogue for sparc64.
369369
......@@ -490,13 +490,14 @@ fn gen(self: *Self) !void {
490490}
491491
492492fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
493 const mod = self.bin_file.options.module.?;
494 const ip = &mod.intern_pool;
493495 const air_tags = self.air.instructions.items(.tag);
494496
495497 for (body) |inst| {
496498 // TODO: remove now-redundant isUnused calls from AIR handler functions
497 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
499 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
498500 continue;
499 }
500501
501502 const old_air_bookkeeping = self.air_bookkeeping;
502503 try self.ensureProcessDeathCapacity(Liveness.bpi);
......@@ -676,8 +677,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
676677 .ptr_elem_val => try self.airPtrElemVal(inst),
677678 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
678679
679 .constant => unreachable, // excluded from function bodies
680 .const_ty => unreachable, // excluded from function bodies
680 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
681681 .unreach => self.finishAirBookkeeping(),
682682
683683 .optional_payload => try self.airOptionalPayload(inst),
......@@ -758,18 +758,18 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
758758 const tag = self.air.instructions.items(.tag)[inst];
759759 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
760760 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
761 const mod = self.bin_file.options.module.?;
761762 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
762763 const lhs = try self.resolveInst(extra.lhs);
763764 const rhs = try self.resolveInst(extra.rhs);
764 const lhs_ty = self.air.typeOf(extra.lhs);
765 const rhs_ty = self.air.typeOf(extra.rhs);
765 const lhs_ty = self.typeOf(extra.lhs);
766 const rhs_ty = self.typeOf(extra.rhs);
766767
767 switch (lhs_ty.zigTypeTag()) {
768 switch (lhs_ty.zigTypeTag(mod)) {
768769 .Vector => return self.fail("TODO implement add_with_overflow/sub_with_overflow for vectors", .{}),
769770 .Int => {
770 const mod = self.bin_file.options.module.?;
771771 assert(lhs_ty.eql(rhs_ty, mod));
772 const int_info = lhs_ty.intInfo(self.target.*);
772 const int_info = lhs_ty.intInfo(mod);
773773 switch (int_info.bits) {
774774 32, 64 => {
775775 // Only say yes if the operation is
......@@ -836,8 +836,9 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
836836}
837837
838838fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
839 const vector_ty = self.air.typeOfIndex(inst);
840 const len = vector_ty.vectorLen();
839 const mod = self.bin_file.options.module.?;
840 const vector_ty = self.typeOfIndex(inst);
841 const len = vector_ty.vectorLen(mod);
841842 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
842843 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
843844 const result: MCValue = res: {
......@@ -869,19 +870,20 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
869870}
870871
871872fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
873 const mod = self.bin_file.options.module.?;
872874 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
873875 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
874 const ptr_ty = self.air.typeOf(ty_op.operand);
876 const ptr_ty = self.typeOf(ty_op.operand);
875877 const ptr = try self.resolveInst(ty_op.operand);
876 const array_ty = ptr_ty.childType();
877 const array_len = @intCast(u32, array_ty.arrayLen());
878 const array_ty = ptr_ty.childType(mod);
879 const array_len = @intCast(u32, array_ty.arrayLen(mod));
878880
879881 const ptr_bits = self.target.ptrBitWidth();
880882 const ptr_bytes = @divExact(ptr_bits, 8);
881883
882884 const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2);
883885 try self.genSetStack(ptr_ty, stack_offset, ptr);
884 try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len });
886 try self.genSetStack(Type.usize, stack_offset - ptr_bytes, .{ .immediate = array_len });
885887 break :result MCValue{ .stack_offset = stack_offset };
886888 };
887889 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -935,7 +937,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
935937
936938 const arg_mcv = try self.resolveInst(input);
937939 try self.register_manager.getReg(reg, null);
938 try self.genSetReg(self.air.typeOf(input), reg, arg_mcv);
940 try self.genSetReg(self.typeOf(input), reg, arg_mcv);
939941 }
940942
941943 {
......@@ -1008,17 +1010,17 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
10081010}
10091011
10101012fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1013 const mod = self.bin_file.options.module.?;
10111014 const arg_index = self.arg_index;
10121015 self.arg_index += 1;
10131016
1014 const ty = self.air.typeOfIndex(inst);
1017 const ty = self.typeOfIndex(inst);
10151018
10161019 const arg = self.args[arg_index];
10171020 const mcv = blk: {
10181021 switch (arg) {
10191022 .stack_offset => |off| {
1020 const mod = self.bin_file.options.module.?;
1021 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse {
1023 const abi_size = math.cast(u32, ty.abiSize(mod)) orelse {
10221024 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
10231025 };
10241026 const offset = off + abi_size;
......@@ -1063,8 +1065,8 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void {
10631065 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
10641066 const lhs = try self.resolveInst(bin_op.lhs);
10651067 const rhs = try self.resolveInst(bin_op.rhs);
1066 const lhs_ty = self.air.typeOf(bin_op.lhs);
1067 const rhs_ty = self.air.typeOf(bin_op.rhs);
1068 const lhs_ty = self.typeOf(bin_op.lhs);
1069 const rhs_ty = self.typeOf(bin_op.rhs);
10681070 const result: MCValue = if (self.liveness.isUnused(inst))
10691071 .dead
10701072 else
......@@ -1088,8 +1090,8 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
10881090 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
10891091 const lhs = try self.resolveInst(bin_op.lhs);
10901092 const rhs = try self.resolveInst(bin_op.rhs);
1091 const lhs_ty = self.air.typeOf(bin_op.lhs);
1092 const rhs_ty = self.air.typeOf(bin_op.rhs);
1093 const lhs_ty = self.typeOf(bin_op.lhs);
1094 const rhs_ty = self.typeOf(bin_op.rhs);
10931095 const result: MCValue = if (self.liveness.isUnused(inst))
10941096 .dead
10951097 else
......@@ -1115,7 +1117,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
11151117 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
11161118
11171119 const dest = try self.allocRegOrMem(inst, true);
1118 try self.setRegOrMem(self.air.typeOfIndex(inst), dest, operand);
1120 try self.setRegOrMem(self.typeOfIndex(inst), dest, operand);
11191121 break :result dest;
11201122 };
11211123 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -1203,6 +1205,7 @@ fn airBreakpoint(self: *Self) !void {
12031205}
12041206
12051207fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
1208 const mod = self.bin_file.options.module.?;
12061209 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
12071210
12081211 // We have hardware byteswapper in SPARCv9, don't let mainstream compilers mislead you.
......@@ -1217,15 +1220,15 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
12171220 // TODO: Fold byteswap+store into a single ST*A and load+byteswap into a single LD*A.
12181221 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
12191222 const operand = try self.resolveInst(ty_op.operand);
1220 const operand_ty = self.air.typeOf(ty_op.operand);
1221 switch (operand_ty.zigTypeTag()) {
1223 const operand_ty = self.typeOf(ty_op.operand);
1224 switch (operand_ty.zigTypeTag(mod)) {
12221225 .Vector => return self.fail("TODO byteswap for vectors", .{}),
12231226 .Int => {
1224 const int_info = operand_ty.intInfo(self.target.*);
1227 const int_info = operand_ty.intInfo(mod);
12251228 if (int_info.bits == 8) break :result operand;
12261229
12271230 const abi_size = int_info.bits >> 3;
1228 const abi_align = operand_ty.abiAlignment(self.target.*);
1231 const abi_align = operand_ty.abiAlignment(mod);
12291232 const opposite_endian_asi = switch (self.target.cpu.arch.endian()) {
12301233 Endian.Big => ASI.asi_primary_little,
12311234 Endian.Little => ASI.asi_primary,
......@@ -1293,10 +1296,11 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
12931296 const callee = pl_op.operand;
12941297 const extra = self.air.extraData(Air.Call, pl_op.payload);
12951298 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end .. extra.end + extra.data.args_len]);
1296 const ty = self.air.typeOf(callee);
1297 const fn_ty = switch (ty.zigTypeTag()) {
1299 const ty = self.typeOf(callee);
1300 const mod = self.bin_file.options.module.?;
1301 const fn_ty = switch (ty.zigTypeTag(mod)) {
12981302 .Fn => ty,
1299 .Pointer => ty.childType(),
1303 .Pointer => ty.childType(mod),
13001304 else => unreachable,
13011305 };
13021306
......@@ -1316,7 +1320,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13161320
13171321 for (info.args, 0..) |mc_arg, arg_i| {
13181322 const arg = args[arg_i];
1319 const arg_ty = self.air.typeOf(arg);
1323 const arg_ty = self.typeOf(arg);
13201324 const arg_mcv = try self.resolveInst(arg);
13211325
13221326 switch (mc_arg) {
......@@ -1337,10 +1341,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13371341
13381342 // Due to incremental compilation, how function calls are generated depends
13391343 // on linking.
1340 if (self.air.value(callee)) |func_value| {
1344 if (try self.air.value(callee, mod)) |func_value| {
13411345 if (self.bin_file.tag == link.File.Elf.base_tag) {
1342 if (func_value.castTag(.function)) |func_payload| {
1343 const func = func_payload.data;
1346 if (mod.funcPtrUnwrap(mod.intern_pool.indexToFunc(func_value.ip_index))) |func| {
13441347 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
13451348 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
13461349 const atom = elf_file.getAtom(atom_index);
......@@ -1348,7 +1351,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13481351 break :blk @intCast(u32, atom.getOffsetTableAddress(elf_file));
13491352 } else unreachable;
13501353
1351 try self.genSetReg(Type.initTag(.usize), .o7, .{ .memory = got_addr });
1354 try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });
13521355
13531356 _ = try self.addInst(.{
13541357 .tag = .jmpl,
......@@ -1367,14 +1370,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
13671370 .tag = .nop,
13681371 .data = .{ .nop = {} },
13691372 });
1370 } else if (func_value.castTag(.extern_fn)) |_| {
1373 } else if (mod.intern_pool.indexToKey(func_value.ip_index) == .extern_func) {
13711374 return self.fail("TODO implement calling extern functions", .{});
13721375 } else {
13731376 return self.fail("TODO implement calling bitcasted functions", .{});
13741377 }
13751378 } else @panic("TODO SPARCv9 currently does not support non-ELF binaries");
13761379 } else {
1377 assert(ty.zigTypeTag() == .Pointer);
1380 assert(ty.zigTypeTag(mod) == .Pointer);
13781381 const mcv = try self.resolveInst(callee);
13791382 try self.genSetReg(ty, .o7, mcv);
13801383
......@@ -1422,25 +1425,24 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
14221425
14231426fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
14241427 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1428 const mod = self.bin_file.options.module.?;
14251429 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
14261430 const lhs = try self.resolveInst(bin_op.lhs);
14271431 const rhs = try self.resolveInst(bin_op.rhs);
1428 const lhs_ty = self.air.typeOf(bin_op.lhs);
1432 const lhs_ty = self.typeOf(bin_op.lhs);
14291433
1430 var int_buffer: Type.Payload.Bits = undefined;
1431 const int_ty = switch (lhs_ty.zigTypeTag()) {
1434 const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
14321435 .Vector => unreachable, // Handled by cmp_vector.
1433 .Enum => lhs_ty.intTagType(&int_buffer),
1436 .Enum => lhs_ty.intTagType(mod),
14341437 .Int => lhs_ty,
1435 .Bool => Type.initTag(.u1),
1438 .Bool => Type.u1,
14361439 .Pointer => Type.usize,
1437 .ErrorSet => Type.initTag(.u16),
1440 .ErrorSet => Type.u16,
14381441 .Optional => blk: {
1439 var opt_buffer: Type.Payload.ElemType = undefined;
1440 const payload_ty = lhs_ty.optionalChild(&opt_buffer);
1441 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1442 break :blk Type.initTag(.u1);
1443 } else if (lhs_ty.isPtrLikeOptional()) {
1442 const payload_ty = lhs_ty.optionalChild(mod);
1443 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1444 break :blk Type.u1;
1445 } else if (lhs_ty.isPtrLikeOptional(mod)) {
14441446 break :blk Type.usize;
14451447 } else {
14461448 return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{});
......@@ -1450,7 +1452,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
14501452 else => unreachable,
14511453 };
14521454
1453 const int_info = int_ty.intInfo(self.target.*);
1455 const int_info = int_ty.intInfo(mod);
14541456 if (int_info.bits <= 64) {
14551457 _ = try self.binOp(.cmp_eq, lhs, rhs, int_ty, int_ty, BinOpMetadata{
14561458 .lhs = bin_op.lhs,
......@@ -1512,8 +1514,8 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
15121514 // whether it needs to be spilled in the branches
15131515 if (self.liveness.operandDies(inst, 0)) {
15141516 const op_int = @enumToInt(pl_op.operand);
1515 if (op_int >= Air.Inst.Ref.typed_value_map.len) {
1516 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
1517 if (op_int >= Air.ref_start_index) {
1518 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
15171519 self.processDeath(op_index);
15181520 }
15191521 }
......@@ -1603,7 +1605,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
16031605 log.debug("consolidating else_entry {d} {}=>{}", .{ else_key, else_value, canon_mcv });
16041606 // TODO make sure the destination stack offset / register does not already have something
16051607 // going on there.
1606 try self.setRegOrMem(self.air.typeOfIndex(else_key), canon_mcv, else_value);
1608 try self.setRegOrMem(self.typeOfIndex(else_key), canon_mcv, else_value);
16071609 // TODO track the new register / stack allocation
16081610 }
16091611 try parent_branch.inst_table.ensureUnusedCapacity(self.gpa, saved_then_branch.inst_table.count());
......@@ -1630,7 +1632,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
16301632 log.debug("consolidating then_entry {d} {}=>{}", .{ then_key, parent_mcv, then_value });
16311633 // TODO make sure the destination stack offset / register does not already have something
16321634 // going on there.
1633 try self.setRegOrMem(self.air.typeOfIndex(then_key), parent_mcv, then_value);
1635 try self.setRegOrMem(self.typeOfIndex(then_key), parent_mcv, then_value);
16341636 // TODO track the new register / stack allocation
16351637 }
16361638
......@@ -1656,8 +1658,9 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
16561658}
16571659
16581660fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
1659 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1660 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
1661 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
1662 const mod = self.bin_file.options.module.?;
1663 const function = mod.funcPtr(ty_fn.func);
16611664 // TODO emit debug info for function change
16621665 _ = function;
16631666 return self.finishAir(inst, .dead, .{ .none, .none, .none });
......@@ -1752,10 +1755,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
17521755 if (self.liveness.isUnused(inst))
17531756 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
17541757
1755 const operand_ty = self.air.typeOf(ty_op.operand);
1758 const mod = self.bin_file.options.module.?;
1759 const operand_ty = self.typeOf(ty_op.operand);
17561760 const operand = try self.resolveInst(ty_op.operand);
1757 const info_a = operand_ty.intInfo(self.target.*);
1758 const info_b = self.air.typeOfIndex(inst).intInfo(self.target.*);
1761 const info_a = operand_ty.intInfo(mod);
1762 const info_b = self.typeOfIndex(inst).intInfo(mod);
17591763 if (info_a.signedness != info_b.signedness)
17601764 return self.fail("TODO gen intcast sign safety in semantic analysis", .{});
17611765
......@@ -1777,7 +1781,7 @@ fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
17771781 const un_op = self.air.instructions.items(.data)[inst].un_op;
17781782 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
17791783 const operand = try self.resolveInst(un_op);
1780 const ty = self.air.typeOf(un_op);
1784 const ty = self.typeOf(un_op);
17811785 break :result try self.isErr(ty, operand);
17821786 };
17831787 return self.finishAir(inst, result, .{ un_op, .none, .none });
......@@ -1787,7 +1791,7 @@ fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
17871791 const un_op = self.air.instructions.items(.data)[inst].un_op;
17881792 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
17891793 const operand = try self.resolveInst(un_op);
1790 const ty = self.air.typeOf(un_op);
1794 const ty = self.typeOf(un_op);
17911795 break :result try self.isNonErr(ty, operand);
17921796 };
17931797 return self.finishAir(inst, result, .{ un_op, .none, .none });
......@@ -1812,15 +1816,16 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
18121816}
18131817
18141818fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
1819 const mod = self.bin_file.options.module.?;
18151820 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1816 const elem_ty = self.air.typeOfIndex(inst);
1817 const elem_size = elem_ty.abiSize(self.target.*);
1821 const elem_ty = self.typeOfIndex(inst);
1822 const elem_size = elem_ty.abiSize(mod);
18181823 const result: MCValue = result: {
1819 if (!elem_ty.hasRuntimeBits())
1824 if (!elem_ty.hasRuntimeBits(mod))
18201825 break :result MCValue.none;
18211826
18221827 const ptr = try self.resolveInst(ty_op.operand);
1823 const is_volatile = self.air.typeOf(ty_op.operand).isVolatilePtr();
1828 const is_volatile = self.typeOf(ty_op.operand).isVolatilePtr(mod);
18241829 if (self.liveness.isUnused(inst) and !is_volatile)
18251830 break :result MCValue.dead;
18261831
......@@ -1835,7 +1840,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
18351840 break :blk try self.allocRegOrMem(inst, true);
18361841 }
18371842 };
1838 try self.load(dst_mcv, ptr, self.air.typeOf(ty_op.operand));
1843 try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand));
18391844 break :result dst_mcv;
18401845 };
18411846 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -1878,8 +1883,8 @@ fn airMinMax(self: *Self, inst: Air.Inst.Index) !void {
18781883 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
18791884 const lhs = try self.resolveInst(bin_op.lhs);
18801885 const rhs = try self.resolveInst(bin_op.rhs);
1881 const lhs_ty = self.air.typeOf(bin_op.lhs);
1882 const rhs_ty = self.air.typeOf(bin_op.rhs);
1886 const lhs_ty = self.typeOf(bin_op.lhs);
1887 const rhs_ty = self.typeOf(bin_op.rhs);
18831888
18841889 const result: MCValue = if (self.liveness.isUnused(inst))
18851890 .dead
......@@ -1893,8 +1898,8 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
18931898 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
18941899 const lhs = try self.resolveInst(bin_op.lhs);
18951900 const rhs = try self.resolveInst(bin_op.rhs);
1896 const lhs_ty = self.air.typeOf(bin_op.lhs);
1897 const rhs_ty = self.air.typeOf(bin_op.rhs);
1901 const lhs_ty = self.typeOf(bin_op.lhs);
1902 const rhs_ty = self.typeOf(bin_op.rhs);
18981903 assert(lhs_ty.eql(rhs_ty, self.bin_file.options.module.?));
18991904
19001905 if (self.liveness.isUnused(inst))
......@@ -2037,18 +2042,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
20372042 //const tag = self.air.instructions.items(.tag)[inst];
20382043 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
20392044 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2045 const mod = self.bin_file.options.module.?;
20402046 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
20412047 const lhs = try self.resolveInst(extra.lhs);
20422048 const rhs = try self.resolveInst(extra.rhs);
2043 const lhs_ty = self.air.typeOf(extra.lhs);
2044 const rhs_ty = self.air.typeOf(extra.rhs);
2049 const lhs_ty = self.typeOf(extra.lhs);
2050 const rhs_ty = self.typeOf(extra.rhs);
20452051
2046 switch (lhs_ty.zigTypeTag()) {
2052 switch (lhs_ty.zigTypeTag(mod)) {
20472053 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
20482054 .Int => {
2049 const mod = self.bin_file.options.module.?;
20502055 assert(lhs_ty.eql(rhs_ty, mod));
2051 const int_info = lhs_ty.intInfo(self.target.*);
2056 const int_info = lhs_ty.intInfo(mod);
20522057 switch (int_info.bits) {
20532058 1...32 => {
20542059 try self.spillConditionFlagsIfOccupied();
......@@ -2101,9 +2106,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
21012106
21022107fn airNot(self: *Self, inst: Air.Inst.Index) !void {
21032108 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2109 const mod = self.bin_file.options.module.?;
21042110 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
21052111 const operand = try self.resolveInst(ty_op.operand);
2106 const operand_ty = self.air.typeOf(ty_op.operand);
2112 const operand_ty = self.typeOf(ty_op.operand);
21072113 switch (operand) {
21082114 .dead => unreachable,
21092115 .unreach => unreachable,
......@@ -2116,7 +2122,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
21162122 };
21172123 },
21182124 else => {
2119 switch (operand_ty.zigTypeTag()) {
2125 switch (operand_ty.zigTypeTag(mod)) {
21202126 .Bool => {
21212127 const op_reg = switch (operand) {
21222128 .register => |r| r,
......@@ -2150,7 +2156,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
21502156 },
21512157 .Vector => return self.fail("TODO bitwise not for vectors", .{}),
21522158 .Int => {
2153 const int_info = operand_ty.intInfo(self.target.*);
2159 const int_info = operand_ty.intInfo(mod);
21542160 if (int_info.bits <= 64) {
21552161 const op_reg = switch (operand) {
21562162 .register => |r| r,
......@@ -2280,8 +2286,8 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {
22802286 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
22812287 const lhs = try self.resolveInst(bin_op.lhs);
22822288 const rhs = try self.resolveInst(bin_op.rhs);
2283 const lhs_ty = self.air.typeOf(bin_op.lhs);
2284 const rhs_ty = self.air.typeOf(bin_op.rhs);
2289 const lhs_ty = self.typeOf(bin_op.lhs);
2290 const rhs_ty = self.typeOf(bin_op.rhs);
22852291
22862292 // TODO add safety check
22872293
......@@ -2332,16 +2338,17 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
23322338fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
23332339 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
23342340 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
2341 const mod = self.bin_file.options.module.?;
23352342 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
23362343 const lhs = try self.resolveInst(extra.lhs);
23372344 const rhs = try self.resolveInst(extra.rhs);
2338 const lhs_ty = self.air.typeOf(extra.lhs);
2339 const rhs_ty = self.air.typeOf(extra.rhs);
2345 const lhs_ty = self.typeOf(extra.lhs);
2346 const rhs_ty = self.typeOf(extra.rhs);
23402347
2341 switch (lhs_ty.zigTypeTag()) {
2348 switch (lhs_ty.zigTypeTag(mod)) {
23422349 .Vector => return self.fail("TODO implement mul_with_overflow for vectors", .{}),
23432350 .Int => {
2344 const int_info = lhs_ty.intInfo(self.target.*);
2351 const int_info = lhs_ty.intInfo(mod);
23452352 if (int_info.bits <= 64) {
23462353 try self.spillConditionFlagsIfOccupied();
23472354
......@@ -2423,9 +2430,9 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
24232430 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
24242431 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
24252432 const ptr = try self.resolveInst(bin_op.lhs);
2426 const ptr_ty = self.air.typeOf(bin_op.lhs);
2433 const ptr_ty = self.typeOf(bin_op.lhs);
24272434 const len = try self.resolveInst(bin_op.rhs);
2428 const len_ty = self.air.typeOf(bin_op.rhs);
2435 const len_ty = self.typeOf(bin_op.rhs);
24292436
24302437 const ptr_bits = self.target.ptrBitWidth();
24312438 const ptr_bytes = @divExact(ptr_bits, 8);
......@@ -2439,6 +2446,7 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
24392446}
24402447
24412448fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2449 const mod = self.bin_file.options.module.?;
24422450 const is_volatile = false; // TODO
24432451 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
24442452
......@@ -2447,12 +2455,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
24472455 const slice_mcv = try self.resolveInst(bin_op.lhs);
24482456 const index_mcv = try self.resolveInst(bin_op.rhs);
24492457
2450 const slice_ty = self.air.typeOf(bin_op.lhs);
2451 const elem_ty = slice_ty.childType();
2452 const elem_size = elem_ty.abiSize(self.target.*);
2458 const slice_ty = self.typeOf(bin_op.lhs);
2459 const elem_ty = slice_ty.childType(mod);
2460 const elem_size = elem_ty.abiSize(mod);
24532461
2454 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2455 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
2462 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
24562463
24572464 const index_lock: ?RegisterLock = if (index_mcv == .register)
24582465 self.register_manager.lockRegAssumeUnused(index_mcv.register)
......@@ -2537,8 +2544,8 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
25372544 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
25382545 const ptr = try self.resolveInst(bin_op.lhs);
25392546 const value = try self.resolveInst(bin_op.rhs);
2540 const ptr_ty = self.air.typeOf(bin_op.lhs);
2541 const value_ty = self.air.typeOf(bin_op.rhs);
2547 const ptr_ty = self.typeOf(bin_op.lhs);
2548 const value_ty = self.typeOf(bin_op.rhs);
25422549
25432550 try self.store(ptr, value, ptr_ty, value_ty);
25442551
......@@ -2564,9 +2571,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
25642571 const operand = extra.struct_operand;
25652572 const index = extra.field_index;
25662573 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2574 const mod = self.bin_file.options.module.?;
25672575 const mcv = try self.resolveInst(operand);
2568 const struct_ty = self.air.typeOf(operand);
2569 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
2576 const struct_ty = self.typeOf(operand);
2577 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
25702578
25712579 switch (mcv) {
25722580 .dead, .unreach => unreachable,
......@@ -2651,8 +2659,8 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
26512659fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
26522660 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
26532661 const operand = try self.resolveInst(ty_op.operand);
2654 const operand_ty = self.air.typeOf(ty_op.operand);
2655 const dest_ty = self.air.typeOfIndex(inst);
2662 const operand_ty = self.typeOf(ty_op.operand);
2663 const dest_ty = self.typeOfIndex(inst);
26562664
26572665 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: {
26582666 break :blk try self.trunc(inst, operand, operand_ty, dest_ty);
......@@ -2666,7 +2674,7 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
26662674 const extra = self.air.extraData(Air.Try, pl_op.payload);
26672675 const body = self.air.extra[extra.end..][0..extra.data.body_len];
26682676 const result: MCValue = result: {
2669 const error_union_ty = self.air.typeOf(pl_op.operand);
2677 const error_union_ty = self.typeOf(pl_op.operand);
26702678 const error_union = try self.resolveInst(pl_op.operand);
26712679 const is_err_result = try self.isErr(error_union_ty, error_union);
26722680 const reloc = try self.condBr(is_err_result);
......@@ -2696,12 +2704,13 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
26962704}
26972705
26982706fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2707 const mod = self.bin_file.options.module.?;
26992708 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27002709 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2701 const error_union_ty = self.air.typeOf(ty_op.operand);
2702 const payload_ty = error_union_ty.errorUnionPayload();
2710 const error_union_ty = self.typeOf(ty_op.operand);
2711 const payload_ty = error_union_ty.errorUnionPayload(mod);
27032712 const mcv = try self.resolveInst(ty_op.operand);
2704 if (!payload_ty.hasRuntimeBits()) break :result mcv;
2713 if (!payload_ty.hasRuntimeBits(mod)) break :result mcv;
27052714
27062715 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
27072716 };
......@@ -2709,11 +2718,12 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
27092718}
27102719
27112720fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
2721 const mod = self.bin_file.options.module.?;
27122722 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27132723 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2714 const error_union_ty = self.air.typeOf(ty_op.operand);
2715 const payload_ty = error_union_ty.errorUnionPayload();
2716 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
2724 const error_union_ty = self.typeOf(ty_op.operand);
2725 const payload_ty = error_union_ty.errorUnionPayload(mod);
2726 if (!payload_ty.hasRuntimeBits(mod)) break :result MCValue.none;
27172727
27182728 return self.fail("TODO implement unwrap error union payload for non-empty payloads", .{});
27192729 };
......@@ -2722,12 +2732,13 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
27222732
27232733/// E to E!T
27242734fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
2735 const mod = self.bin_file.options.module.?;
27252736 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27262737 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
27272738 const error_union_ty = self.air.getRefType(ty_op.ty);
2728 const payload_ty = error_union_ty.errorUnionPayload();
2739 const payload_ty = error_union_ty.errorUnionPayload(mod);
27292740 const mcv = try self.resolveInst(ty_op.operand);
2730 if (!payload_ty.hasRuntimeBits()) break :result mcv;
2741 if (!payload_ty.hasRuntimeBits(mod)) break :result mcv;
27312742
27322743 return self.fail("TODO implement wrap errunion error for non-empty payloads", .{});
27332744 };
......@@ -2742,12 +2753,13 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
27422753}
27432754
27442755fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
2756 const mod = self.bin_file.options.module.?;
27452757 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27462758 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2747 const optional_ty = self.air.typeOfIndex(inst);
2759 const optional_ty = self.typeOfIndex(inst);
27482760
27492761 // Optional with a zero-bit payload type is just a boolean true
2750 if (optional_ty.abiSize(self.target.*) == 1)
2762 if (optional_ty.abiSize(mod) == 1)
27512763 break :result MCValue{ .immediate = 1 };
27522764
27532765 return self.fail("TODO implement wrap optional for {}", .{self.target.cpu.arch});
......@@ -2782,9 +2794,10 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u
27822794
27832795/// Use a pointer instruction as the basis for allocating stack memory.
27842796fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
2785 const elem_ty = self.air.typeOfIndex(inst).elemType();
2797 const mod = self.bin_file.options.module.?;
2798 const elem_ty = self.typeOfIndex(inst).childType(mod);
27862799
2787 if (!elem_ty.hasRuntimeBits()) {
2800 if (!elem_ty.hasRuntimeBits(mod)) {
27882801 // As this stack item will never be dereferenced at runtime,
27892802 // return the stack offset 0. Stack offset 0 will be where all
27902803 // zero-sized stack allocations live as non-zero-sized
......@@ -2792,22 +2805,21 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
27922805 return @as(u32, 0);
27932806 }
27942807
2795 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
2796 const mod = self.bin_file.options.module.?;
2808 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
27972809 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
27982810 };
27992811 // TODO swap this for inst.ty.ptrAlign
2800 const abi_align = elem_ty.abiAlignment(self.target.*);
2812 const abi_align = elem_ty.abiAlignment(mod);
28012813 return self.allocMem(inst, abi_size, abi_align);
28022814}
28032815
28042816fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
2805 const elem_ty = self.air.typeOfIndex(inst);
2806 const abi_size = math.cast(u32, elem_ty.abiSize(self.target.*)) orelse {
2807 const mod = self.bin_file.options.module.?;
2817 const mod = self.bin_file.options.module.?;
2818 const elem_ty = self.typeOfIndex(inst);
2819 const abi_size = math.cast(u32, elem_ty.abiSize(mod)) orelse {
28082820 return self.fail("type '{}' too big to fit into stack frame", .{elem_ty.fmt(mod)});
28092821 };
2810 const abi_align = elem_ty.abiAlignment(self.target.*);
2822 const abi_align = elem_ty.abiAlignment(mod);
28112823 if (abi_align > self.stack_align)
28122824 self.stack_align = abi_align;
28132825
......@@ -2860,12 +2872,12 @@ fn binOp(
28602872 .xor,
28612873 .cmp_eq,
28622874 => {
2863 switch (lhs_ty.zigTypeTag()) {
2875 switch (lhs_ty.zigTypeTag(mod)) {
28642876 .Float => return self.fail("TODO binary operations on floats", .{}),
28652877 .Vector => return self.fail("TODO binary operations on vectors", .{}),
28662878 .Int => {
28672879 assert(lhs_ty.eql(rhs_ty, mod));
2868 const int_info = lhs_ty.intInfo(self.target.*);
2880 const int_info = lhs_ty.intInfo(mod);
28692881 if (int_info.bits <= 64) {
28702882 // Only say yes if the operation is
28712883 // commutative, i.e. we can swap both of the
......@@ -2934,10 +2946,10 @@ fn binOp(
29342946 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
29352947
29362948 // Truncate if necessary
2937 switch (lhs_ty.zigTypeTag()) {
2949 switch (lhs_ty.zigTypeTag(mod)) {
29382950 .Vector => return self.fail("TODO binary operations on vectors", .{}),
29392951 .Int => {
2940 const int_info = lhs_ty.intInfo(self.target.*);
2952 const int_info = lhs_ty.intInfo(mod);
29412953 if (int_info.bits <= 64) {
29422954 const result_reg = result.register;
29432955 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
......@@ -2951,11 +2963,11 @@ fn binOp(
29512963 },
29522964
29532965 .div_trunc => {
2954 switch (lhs_ty.zigTypeTag()) {
2966 switch (lhs_ty.zigTypeTag(mod)) {
29552967 .Vector => return self.fail("TODO binary operations on vectors", .{}),
29562968 .Int => {
29572969 assert(lhs_ty.eql(rhs_ty, mod));
2958 const int_info = lhs_ty.intInfo(self.target.*);
2970 const int_info = lhs_ty.intInfo(mod);
29592971 if (int_info.bits <= 64) {
29602972 const rhs_immediate_ok = switch (tag) {
29612973 .div_trunc => rhs == .immediate and rhs.immediate <= std.math.maxInt(u12),
......@@ -2984,14 +2996,14 @@ fn binOp(
29842996 },
29852997
29862998 .ptr_add => {
2987 switch (lhs_ty.zigTypeTag()) {
2999 switch (lhs_ty.zigTypeTag(mod)) {
29883000 .Pointer => {
29893001 const ptr_ty = lhs_ty;
2990 const elem_ty = switch (ptr_ty.ptrSize()) {
2991 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
2992 else => ptr_ty.childType(),
3002 const elem_ty = switch (ptr_ty.ptrSize(mod)) {
3003 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
3004 else => ptr_ty.childType(mod),
29933005 };
2994 const elem_size = elem_ty.abiSize(self.target.*);
3006 const elem_size = elem_ty.abiSize(mod);
29953007
29963008 if (elem_size == 1) {
29973009 const base_tag: Mir.Inst.Tag = switch (tag) {
......@@ -3005,7 +3017,7 @@ fn binOp(
30053017 // multiplying it with elem_size
30063018
30073019 const offset = try self.binOp(.mul, rhs, .{ .immediate = elem_size }, Type.usize, Type.usize, null);
3008 const addr = try self.binOp(tag, lhs, offset, Type.initTag(.manyptr_u8), Type.usize, null);
3020 const addr = try self.binOp(tag, lhs, offset, Type.manyptr_u8, Type.usize, null);
30093021 return addr;
30103022 }
30113023 },
......@@ -3016,7 +3028,7 @@ fn binOp(
30163028 .bool_and,
30173029 .bool_or,
30183030 => {
3019 switch (lhs_ty.zigTypeTag()) {
3031 switch (lhs_ty.zigTypeTag(mod)) {
30203032 .Bool => {
30213033 assert(lhs != .immediate); // should have been handled by Sema
30223034 assert(rhs != .immediate); // should have been handled by Sema
......@@ -3046,10 +3058,10 @@ fn binOp(
30463058 const result = try self.binOp(base_tag, lhs, rhs, lhs_ty, rhs_ty, metadata);
30473059
30483060 // Truncate if necessary
3049 switch (lhs_ty.zigTypeTag()) {
3061 switch (lhs_ty.zigTypeTag(mod)) {
30503062 .Vector => return self.fail("TODO binary operations on vectors", .{}),
30513063 .Int => {
3052 const int_info = lhs_ty.intInfo(self.target.*);
3064 const int_info = lhs_ty.intInfo(mod);
30533065 if (int_info.bits <= 64) {
30543066 // 32 and 64 bit operands doesn't need truncating
30553067 if (int_info.bits == 32 or int_info.bits == 64) return result;
......@@ -3068,10 +3080,10 @@ fn binOp(
30683080 .shl_exact,
30693081 .shr_exact,
30703082 => {
3071 switch (lhs_ty.zigTypeTag()) {
3083 switch (lhs_ty.zigTypeTag(mod)) {
30723084 .Vector => return self.fail("TODO binary operations on vectors", .{}),
30733085 .Int => {
3074 const int_info = lhs_ty.intInfo(self.target.*);
3086 const int_info = lhs_ty.intInfo(mod);
30753087 if (int_info.bits <= 64) {
30763088 const rhs_immediate_ok = rhs == .immediate;
30773089
......@@ -3393,7 +3405,8 @@ fn binOpRegister(
33933405fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
33943406 const block_data = self.blocks.getPtr(block).?;
33953407
3396 if (self.air.typeOf(operand).hasRuntimeBits()) {
3408 const mod = self.bin_file.options.module.?;
3409 if (self.typeOf(operand).hasRuntimeBits(mod)) {
33973410 const operand_mcv = try self.resolveInst(operand);
33983411 const block_mcv = block_data.mcv;
33993412 if (block_mcv == .none) {
......@@ -3402,13 +3415,13 @@ fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void {
34023415 .register, .stack_offset, .memory => operand_mcv,
34033416 .immediate => blk: {
34043417 const new_mcv = try self.allocRegOrMem(block, true);
3405 try self.setRegOrMem(self.air.typeOfIndex(block), new_mcv, operand_mcv);
3418 try self.setRegOrMem(self.typeOfIndex(block), new_mcv, operand_mcv);
34063419 break :blk new_mcv;
34073420 },
34083421 else => return self.fail("TODO implement block_data.mcv = operand_mcv for {}", .{operand_mcv}),
34093422 };
34103423 } else {
3411 try self.setRegOrMem(self.air.typeOfIndex(block), block_mcv, operand_mcv);
3424 try self.setRegOrMem(self.typeOfIndex(block), block_mcv, operand_mcv);
34123425 }
34133426 }
34143427 return self.brVoid(block);
......@@ -3512,16 +3525,17 @@ fn ensureProcessDeathCapacity(self: *Self, additional_count: usize) !void {
35123525
35133526/// Given an error union, returns the payload
35143527fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
3515 const err_ty = error_union_ty.errorUnionSet();
3516 const payload_ty = error_union_ty.errorUnionPayload();
3517 if (err_ty.errorSetIsEmpty()) {
3528 const mod = self.bin_file.options.module.?;
3529 const err_ty = error_union_ty.errorUnionSet(mod);
3530 const payload_ty = error_union_ty.errorUnionPayload(mod);
3531 if (err_ty.errorSetIsEmpty(mod)) {
35183532 return error_union_mcv;
35193533 }
3520 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3534 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
35213535 return MCValue.none;
35223536 }
35233537
3524 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, self.target.*));
3538 const payload_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
35253539 switch (error_union_mcv) {
35263540 .register => return self.fail("TODO errUnionPayload for registers", .{}),
35273541 .stack_offset => |off| {
......@@ -3555,8 +3569,8 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
35553569 tomb_bits >>= 1;
35563570 if (!dies) continue;
35573571 const op_int = @enumToInt(op);
3558 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;
3559 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
3572 if (op_int < Air.ref_start_index) continue;
3573 const op_index = @intCast(Air.Inst.Index, op_int - Air.ref_start_index);
35603574 self.processDeath(op_index);
35613575 }
35623576 const is_used = @truncate(u1, tomb_bits) == 0;
......@@ -3730,6 +3744,7 @@ fn genLoadASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Reg
37303744}
37313745
37323746fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
3747 const mod = self.bin_file.options.module.?;
37333748 switch (mcv) {
37343749 .dead => unreachable,
37353750 .unreach, .none => return, // Nothing to do.
......@@ -3928,19 +3943,20 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
39283943 // The value is in memory at a hard-coded address.
39293944 // If the type is a pointer, it means the pointer address is at this memory location.
39303945 try self.genSetReg(ty, reg, .{ .immediate = addr });
3931 try self.genLoad(reg, reg, i13, 0, ty.abiSize(self.target.*));
3946 try self.genLoad(reg, reg, i13, 0, ty.abiSize(mod));
39323947 },
39333948 .stack_offset => |off| {
39343949 const real_offset = realStackOffset(off);
39353950 const simm13 = math.cast(i13, real_offset) orelse
39363951 return self.fail("TODO larger stack offsets: {}", .{real_offset});
3937 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(self.target.*));
3952 try self.genLoad(reg, .sp, i13, simm13, ty.abiSize(mod));
39383953 },
39393954 }
39403955}
39413956
39423957fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerError!void {
3943 const abi_size = ty.abiSize(self.target.*);
3958 const mod = self.bin_file.options.module.?;
3959 const abi_size = ty.abiSize(mod);
39443960 switch (mcv) {
39453961 .dead => unreachable,
39463962 .unreach, .none => return, // Nothing to do.
......@@ -3948,7 +3964,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
39483964 if (!self.wantSafety())
39493965 return; // The already existing value will do just fine.
39503966 // TODO Upgrade this to a memset call when we have that available.
3951 switch (ty.abiSize(self.target.*)) {
3967 switch (ty.abiSize(mod)) {
39523968 1 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaa }),
39533969 2 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaa }),
39543970 4 => return self.genSetStack(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }),
......@@ -3974,11 +3990,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
39743990 const reg_lock = self.register_manager.lockReg(rwo.reg);
39753991 defer if (reg_lock) |locked_reg| self.register_manager.unlockReg(locked_reg);
39763992
3977 const wrapped_ty = ty.structFieldType(0);
3993 const wrapped_ty = ty.structFieldType(0, mod);
39783994 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = rwo.reg });
39793995
3980 const overflow_bit_ty = ty.structFieldType(1);
3981 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
3996 const overflow_bit_ty = ty.structFieldType(1, mod);
3997 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, mod));
39823998 const cond_reg = try self.register_manager.allocReg(null, gp);
39833999
39844000 // TODO handle floating point CCRs
......@@ -4024,11 +4040,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
40244040 const reg = try self.copyToTmpRegister(ty, mcv);
40254041 return self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
40264042 } else {
4027 var ptr_ty_payload: Type.Payload.ElemType = .{
4028 .base = .{ .tag = .single_mut_pointer },
4029 .data = ty,
4030 };
4031 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4043 const ptr_ty = try mod.singleMutPtrType(ty);
40324044
40334045 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, gp);
40344046 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
......@@ -4152,13 +4164,14 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue {
41524164}
41534165
41544166fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
4155 const error_type = ty.errorUnionSet();
4156 const payload_type = ty.errorUnionPayload();
4167 const mod = self.bin_file.options.module.?;
4168 const error_type = ty.errorUnionSet(mod);
4169 const payload_type = ty.errorUnionPayload(mod);
41574170
4158 if (!error_type.hasRuntimeBits()) {
4171 if (!error_type.hasRuntimeBits(mod)) {
41594172 return MCValue{ .immediate = 0 }; // always false
4160 } else if (!payload_type.hasRuntimeBits()) {
4161 if (error_type.abiSize(self.target.*) <= 8) {
4173 } else if (!payload_type.hasRuntimeBits(mod)) {
4174 if (error_type.abiSize(mod) <= 8) {
41624175 const reg_mcv: MCValue = switch (operand) {
41634176 .register => operand,
41644177 else => .{ .register = try self.copyToTmpRegister(error_type, operand) },
......@@ -4249,8 +4262,9 @@ fn jump(self: *Self, inst: Mir.Inst.Index) !void {
42494262}
42504263
42514264fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!void {
4252 const elem_ty = ptr_ty.elemType();
4253 const elem_size = elem_ty.abiSize(self.target.*);
4265 const mod = self.bin_file.options.module.?;
4266 const elem_ty = ptr_ty.childType(mod);
4267 const elem_size = elem_ty.abiSize(mod);
42544268
42554269 switch (ptr) {
42564270 .none => unreachable,
......@@ -4321,11 +4335,11 @@ fn minMax(
43214335) InnerError!MCValue {
43224336 const mod = self.bin_file.options.module.?;
43234337 assert(lhs_ty.eql(rhs_ty, mod));
4324 switch (lhs_ty.zigTypeTag()) {
4338 switch (lhs_ty.zigTypeTag(mod)) {
43254339 .Float => return self.fail("TODO min/max on floats", .{}),
43264340 .Vector => return self.fail("TODO min/max on vectors", .{}),
43274341 .Int => {
4328 const int_info = lhs_ty.intInfo(self.target.*);
4342 const int_info = lhs_ty.intInfo(mod);
43294343 if (int_info.bits <= 64) {
43304344 // TODO skip register setting when one of the operands
43314345 // is a small (fits in i13) immediate.
......@@ -4406,8 +4420,7 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index) !void {
44064420
44074421/// Asserts there is already capacity to insert into top branch inst_table.
44084422fn processDeath(self: *Self, inst: Air.Inst.Index) void {
4409 const air_tags = self.air.instructions.items(.tag);
4410 if (air_tags[inst] == .constant) return; // Constants are immortal.
4423 assert(self.air.instructions.items(.tag)[inst] != .interned);
44114424 // When editing this function, note that the logic must synchronize with `reuseOperand`.
44124425 const prev_value = self.getResolvedInstValue(inst);
44134426 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -4441,12 +4454,11 @@ fn realStackOffset(off: u32) u32 {
44414454
44424455/// Caller must call `CallMCValues.deinit`.
44434456fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView) !CallMCValues {
4444 const cc = fn_ty.fnCallingConvention();
4445 const param_types = try self.gpa.alloc(Type, fn_ty.fnParamLen());
4446 defer self.gpa.free(param_types);
4447 fn_ty.fnParamTypes(param_types);
4457 const mod = self.bin_file.options.module.?;
4458 const fn_info = mod.typeToFunc(fn_ty).?;
4459 const cc = fn_info.cc;
44484460 var result: CallMCValues = .{
4449 .args = try self.gpa.alloc(MCValue, param_types.len),
4461 .args = try self.gpa.alloc(MCValue, fn_info.param_types.len),
44504462 // These undefined values must be populated before returning from this function.
44514463 .return_value = undefined,
44524464 .stack_byte_count = undefined,
......@@ -4454,7 +4466,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44544466 };
44554467 errdefer self.gpa.free(result.args);
44564468
4457 const ret_ty = fn_ty.fnReturnType();
4469 const ret_ty = fn_ty.fnReturnType(mod);
44584470
44594471 switch (cc) {
44604472 .Naked => {
......@@ -4477,8 +4489,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
44774489 .callee => abi.c_abi_int_param_regs_callee_view,
44784490 };
44794491
4480 for (param_types, 0..) |ty, i| {
4481 const param_size = @intCast(u32, ty.abiSize(self.target.*));
4492 for (fn_info.param_types, 0..) |ty, i| {
4493 const param_size = @intCast(u32, ty.toType().abiSize(mod));
44824494 if (param_size <= 8) {
44834495 if (next_register < argument_registers.len) {
44844496 result.args[i] = .{ .register = argument_registers[next_register] };
......@@ -4505,12 +4517,12 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
45054517 result.stack_byte_count = next_stack_offset;
45064518 result.stack_align = 16;
45074519
4508 if (ret_ty.zigTypeTag() == .NoReturn) {
4520 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
45094521 result.return_value = .{ .unreach = {} };
4510 } else if (!ret_ty.hasRuntimeBits()) {
4522 } else if (!ret_ty.hasRuntimeBits(mod)) {
45114523 result.return_value = .{ .none = {} };
45124524 } else {
4513 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
4525 const ret_ty_size = @intCast(u32, ret_ty.abiSize(mod));
45144526 // The callee puts the return values in %i0-%i3, which becomes %o0-%o3 inside the caller.
45154527 if (ret_ty_size <= 8) {
45164528 result.return_value = switch (role) {
......@@ -4528,44 +4540,41 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type, role: RegisterView)
45284540 return result;
45294541}
45304542
4531fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
4532 // First section of indexes correspond to a set number of constant values.
4533 const ref_int = @enumToInt(inst);
4534 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
4535 const tv = Air.Inst.Ref.typed_value_map[ref_int];
4536 if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) {
4537 return MCValue{ .none = {} };
4538 }
4539 return self.genTypedValue(tv);
4540 }
4543fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
4544 const mod = self.bin_file.options.module.?;
4545 const ty = self.typeOf(ref);
45414546
45424547 // If the type has no codegen bits, no need to store it.
4543 const inst_ty = self.air.typeOf(inst);
4544 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())
4545 return MCValue{ .none = {} };
4546
4547 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
4548 switch (self.air.instructions.items(.tag)[inst_index]) {
4549 .constant => {
4550 // Constants have static lifetimes, so they are always memoized in the outer most table.
4551 const branch = &self.branch_stack.items[0];
4552 const gop = try branch.inst_table.getOrPut(self.gpa, inst_index);
4553 if (!gop.found_existing) {
4554 const ty_pl = self.air.instructions.items(.data)[inst_index].ty_pl;
4555 gop.value_ptr.* = try self.genTypedValue(.{
4556 .ty = inst_ty,
4557 .val = self.air.values[ty_pl.payload],
4558 });
4559 }
4560 return gop.value_ptr.*;
4561 },
4562 .const_ty => unreachable,
4563 else => return self.getResolvedInstValue(inst_index),
4548 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
4549
4550 if (Air.refToIndex(ref)) |inst| {
4551 switch (self.air.instructions.items(.tag)[inst]) {
4552 .interned => {
4553 // Constants have static lifetimes, so they are always memoized in the outer most table.
4554 const branch = &self.branch_stack.items[0];
4555 const gop = try branch.inst_table.getOrPut(self.gpa, inst);
4556 if (!gop.found_existing) {
4557 const interned = self.air.instructions.items(.data)[inst].interned;
4558 gop.value_ptr.* = try self.genTypedValue(.{
4559 .ty = ty,
4560 .val = interned.toValue(),
4561 });
4562 }
4563 return gop.value_ptr.*;
4564 },
4565 else => return self.getResolvedInstValue(inst),
4566 }
45644567 }
4568
4569 return self.genTypedValue(.{
4570 .ty = ty,
4571 .val = (try self.air.value(ref, mod)).?,
4572 });
45654573}
45664574
45674575fn ret(self: *Self, mcv: MCValue) !void {
4568 const ret_ty = self.fn_type.fnReturnType();
4576 const mod = self.bin_file.options.module.?;
4577 const ret_ty = self.fn_type.fnReturnType(mod);
45694578 try self.setRegOrMem(ret_ty, self.ret_mcv, mcv);
45704579
45714580 // Just add space for a branch instruction, patch this later
......@@ -4638,7 +4647,7 @@ fn spillConditionFlagsIfOccupied(self: *Self) !void {
46384647 else => unreachable, // mcv doesn't occupy the compare flags
46394648 };
46404649
4641 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
4650 try self.setRegOrMem(self.typeOfIndex(inst_to_save), new_mcv, mcv);
46424651 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
46434652
46444653 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
......@@ -4662,11 +4671,12 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
46624671 assert(reg == reg_mcv.register);
46634672 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
46644673 try branch.inst_table.put(self.gpa, inst, stack_mcv);
4665 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
4674 try self.genSetStack(self.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv);
46664675}
46674676
46684677fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type) InnerError!void {
4669 const abi_size = value_ty.abiSize(self.target.*);
4678 const mod = self.bin_file.options.module.?;
4679 const abi_size = value_ty.abiSize(mod);
46704680
46714681 switch (ptr) {
46724682 .none => unreachable,
......@@ -4707,10 +4717,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
47074717
47084718fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
47094719 return if (self.liveness.isUnused(inst)) .dead else result: {
4720 const mod = self.bin_file.options.module.?;
47104721 const mcv = try self.resolveInst(operand);
4711 const ptr_ty = self.air.typeOf(operand);
4712 const struct_ty = ptr_ty.childType();
4713 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
4722 const ptr_ty = self.typeOf(operand);
4723 const struct_ty = ptr_ty.childType(mod);
4724 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, mod));
47144725 switch (mcv) {
47154726 .ptr_stack_offset => |off| {
47164727 break :result MCValue{ .ptr_stack_offset = off - struct_field_offset };
......@@ -4748,8 +4759,9 @@ fn trunc(
47484759 operand_ty: Type,
47494760 dest_ty: Type,
47504761) !MCValue {
4751 const info_a = operand_ty.intInfo(self.target.*);
4752 const info_b = dest_ty.intInfo(self.target.*);
4762 const mod = self.bin_file.options.module.?;
4763 const info_a = operand_ty.intInfo(mod);
4764 const info_b = dest_ty.intInfo(mod);
47534765
47544766 if (info_b.bits <= 64) {
47554767 const operand_reg = switch (operand) {
......@@ -4866,3 +4878,13 @@ fn wantSafety(self: *Self) bool {
48664878 .ReleaseSmall => false,
48674879 };
48684880}
4881
4882fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
4883 const mod = self.bin_file.options.module.?;
4884 return self.air.typeOf(inst, &mod.intern_pool);
4885}
4886
4887fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
4888 const mod = self.bin_file.options.module.?;
4889 return self.air.typeOfIndex(inst, &mod.intern_pool);
4890}
src/arch/wasm/CodeGen.zig+1035-920
......@@ -11,6 +11,7 @@ const log = std.log.scoped(.codegen);
1111
1212const codegen = @import("../../codegen.zig");
1313const Module = @import("../../Module.zig");
14const InternPool = @import("../../InternPool.zig");
1415const Decl = Module.Decl;
1516const Type = @import("../../type.zig").Type;
1617const Value = @import("../../value.zig").Value;
......@@ -764,8 +765,9 @@ pub fn deinit(func: *CodeGen) void {
764765
765766/// Sets `err_msg` on `CodeGen` and returns `error.CodegenFail` which is caught in link/Wasm.zig
766767fn fail(func: *CodeGen, comptime fmt: []const u8, args: anytype) InnerError {
768 const mod = func.bin_file.base.options.module.?;
767769 const src = LazySrcLoc.nodeOffset(0);
768 const src_loc = src.toSrcLoc(func.decl);
770 const src_loc = src.toSrcLoc(func.decl, mod);
769771 func.err_msg = try Module.ErrorMsg.create(func.gpa, src_loc, fmt, args);
770772 return error.CodegenFail;
771773}
......@@ -788,9 +790,10 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
788790 const gop = try func.branches.items[0].values.getOrPut(func.gpa, ref);
789791 assert(!gop.found_existing);
790792
791 const val = func.air.value(ref).?;
792 const ty = func.air.typeOf(ref);
793 if (!ty.hasRuntimeBitsIgnoreComptime() and !ty.isInt() and !ty.isError()) {
793 const mod = func.bin_file.base.options.module.?;
794 const val = (try func.air.value(ref, mod)).?;
795 const ty = func.typeOf(ref);
796 if (!ty.hasRuntimeBitsIgnoreComptime(mod) and !ty.isInt(mod) and !ty.isError(mod)) {
794797 gop.value_ptr.* = WValue{ .none = {} };
795798 return gop.value_ptr.*;
796799 }
......@@ -801,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
801804 //
802805 // In the other cases, we will simply lower the constant to a value that fits
803806 // into a single local (such as a pointer, integer, bool, etc).
804 const result = if (isByRef(ty, func.target)) blk: {
807 const result = if (isByRef(ty, mod)) blk: {
805808 const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index);
806809 break :blk WValue{ .memory = sym_index };
807810 } else try func.lowerConstant(val, ty);
......@@ -880,7 +883,7 @@ fn iterateBigTomb(func: *CodeGen, inst: Air.Inst.Index, operand_count: usize) !B
880883
881884fn processDeath(func: *CodeGen, ref: Air.Inst.Ref) void {
882885 const inst = Air.refToIndex(ref) orelse return;
883 if (func.air.instructions.items(.tag)[inst] == .constant) return;
886 assert(func.air.instructions.items(.tag)[inst] != .interned);
884887 // Branches are currently only allowed to free locals allocated
885888 // within their own branch.
886889 // TODO: Upon branch consolidation free any locals if needed.
......@@ -987,8 +990,9 @@ fn addExtraAssumeCapacity(func: *CodeGen, extra: anytype) error{OutOfMemory}!u32
987990}
988991
989992/// Using a given `Type`, returns the corresponding type
990fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
991 return switch (ty.zigTypeTag()) {
993fn typeToValtype(ty: Type, mod: *Module) wasm.Valtype {
994 const target = mod.getTarget();
995 return switch (ty.zigTypeTag(mod)) {
992996 .Float => blk: {
993997 const bits = ty.floatBits(target);
994998 if (bits == 16) return wasm.Valtype.i32; // stored/loaded as u16
......@@ -998,30 +1002,26 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
9981002 return wasm.Valtype.i32; // represented as pointer to stack
9991003 },
10001004 .Int, .Enum => blk: {
1001 const info = ty.intInfo(target);
1005 const info = ty.intInfo(mod);
10021006 if (info.bits <= 32) break :blk wasm.Valtype.i32;
10031007 if (info.bits > 32 and info.bits <= 128) break :blk wasm.Valtype.i64;
10041008 break :blk wasm.Valtype.i32; // represented as pointer to stack
10051009 },
1006 .Struct => switch (ty.containerLayout()) {
1010 .Struct => switch (ty.containerLayout(mod)) {
10071011 .Packed => {
1008 const struct_obj = ty.castTag(.@"struct").?.data;
1009 return typeToValtype(struct_obj.backing_int_ty, target);
1012 const struct_obj = mod.typeToStruct(ty).?;
1013 return typeToValtype(struct_obj.backing_int_ty, mod);
10101014 },
10111015 else => wasm.Valtype.i32,
10121016 },
1013 .Vector => switch (determineSimdStoreStrategy(ty, target)) {
1017 .Vector => switch (determineSimdStoreStrategy(ty, mod)) {
10141018 .direct => wasm.Valtype.v128,
10151019 .unrolled => wasm.Valtype.i32,
10161020 },
1017 .Union => switch (ty.containerLayout()) {
1021 .Union => switch (ty.containerLayout(mod)) {
10181022 .Packed => {
1019 var int_ty_payload: Type.Payload.Bits = .{
1020 .base = .{ .tag = .int_unsigned },
1021 .data = @intCast(u16, ty.bitSize(target)),
1022 };
1023 const int_ty = Type.initPayload(&int_ty_payload.base);
1024 return typeToValtype(int_ty, target);
1023 const int_ty = mod.intType(.unsigned, @intCast(u16, ty.bitSize(mod))) catch @panic("out of memory");
1024 return typeToValtype(int_ty, mod);
10251025 },
10261026 else => wasm.Valtype.i32,
10271027 },
......@@ -1030,17 +1030,17 @@ fn typeToValtype(ty: Type, target: std.Target) wasm.Valtype {
10301030}
10311031
10321032/// Using a given `Type`, returns the byte representation of its wasm value type
1033fn genValtype(ty: Type, target: std.Target) u8 {
1034 return wasm.valtype(typeToValtype(ty, target));
1033fn genValtype(ty: Type, mod: *Module) u8 {
1034 return wasm.valtype(typeToValtype(ty, mod));
10351035}
10361036
10371037/// Using a given `Type`, returns the corresponding wasm value type
10381038/// Differently from `genValtype` this also allows `void` to create a block
10391039/// with no return type
1040fn genBlockType(ty: Type, target: std.Target) u8 {
1041 return switch (ty.tag()) {
1042 .void, .noreturn => wasm.block_empty,
1043 else => genValtype(ty, target),
1040fn genBlockType(ty: Type, mod: *Module) u8 {
1041 return switch (ty.ip_index) {
1042 .void_type, .noreturn_type => wasm.block_empty,
1043 else => genValtype(ty, mod),
10441044 };
10451045}
10461046
......@@ -1101,7 +1101,8 @@ fn getResolvedInst(func: *CodeGen, ref: Air.Inst.Ref) *WValue {
11011101/// Creates one locals for a given `Type`.
11021102/// Returns a corresponding `Wvalue` with `local` as active tag
11031103fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
1104 const valtype = typeToValtype(ty, func.target);
1104 const mod = func.bin_file.base.options.module.?;
1105 const valtype = typeToValtype(ty, mod);
11051106 switch (valtype) {
11061107 .i32 => if (func.free_locals_i32.popOrNull()) |index| {
11071108 log.debug("reusing local ({d}) of type {}", .{ index, valtype });
......@@ -1132,7 +1133,8 @@ fn allocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
11321133/// Ensures a new local will be created. This is useful when it's useful
11331134/// to use a zero-initialized local.
11341135fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
1135 try func.locals.append(func.gpa, genValtype(ty, func.target));
1136 const mod = func.bin_file.base.options.module.?;
1137 try func.locals.append(func.gpa, genValtype(ty, mod));
11361138 const initial_index = func.local_index;
11371139 func.local_index += 1;
11381140 return WValue{ .local = .{ .value = initial_index, .references = 1 } };
......@@ -1140,48 +1142,55 @@ fn ensureAllocLocal(func: *CodeGen, ty: Type) InnerError!WValue {
11401142
11411143/// Generates a `wasm.Type` from a given function type.
11421144/// Memory is owned by the caller.
1143fn genFunctype(gpa: Allocator, cc: std.builtin.CallingConvention, params: []const Type, return_type: Type, target: std.Target) !wasm.Type {
1145fn genFunctype(
1146 gpa: Allocator,
1147 cc: std.builtin.CallingConvention,
1148 params: []const InternPool.Index,
1149 return_type: Type,
1150 mod: *Module,
1151) !wasm.Type {
11441152 var temp_params = std.ArrayList(wasm.Valtype).init(gpa);
11451153 defer temp_params.deinit();
11461154 var returns = std.ArrayList(wasm.Valtype).init(gpa);
11471155 defer returns.deinit();
11481156
1149 if (firstParamSRet(cc, return_type, target)) {
1157 if (firstParamSRet(cc, return_type, mod)) {
11501158 try temp_params.append(.i32); // memory address is always a 32-bit handle
1151 } else if (return_type.hasRuntimeBitsIgnoreComptime()) {
1159 } else if (return_type.hasRuntimeBitsIgnoreComptime(mod)) {
11521160 if (cc == .C) {
1153 const res_classes = abi.classifyType(return_type, target);
1161 const res_classes = abi.classifyType(return_type, mod);
11541162 assert(res_classes[0] == .direct and res_classes[1] == .none);
1155 const scalar_type = abi.scalarType(return_type, target);
1156 try returns.append(typeToValtype(scalar_type, target));
1163 const scalar_type = abi.scalarType(return_type, mod);
1164 try returns.append(typeToValtype(scalar_type, mod));
11571165 } else {
1158 try returns.append(typeToValtype(return_type, target));
1166 try returns.append(typeToValtype(return_type, mod));
11591167 }
1160 } else if (return_type.isError()) {
1168 } else if (return_type.isError(mod)) {
11611169 try returns.append(.i32);
11621170 }
11631171
11641172 // param types
1165 for (params) |param_type| {
1166 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1173 for (params) |param_type_ip| {
1174 const param_type = param_type_ip.toType();
1175 if (!param_type.hasRuntimeBitsIgnoreComptime(mod)) continue;
11671176
11681177 switch (cc) {
11691178 .C => {
1170 const param_classes = abi.classifyType(param_type, target);
1179 const param_classes = abi.classifyType(param_type, mod);
11711180 for (param_classes) |class| {
11721181 if (class == .none) continue;
11731182 if (class == .direct) {
1174 const scalar_type = abi.scalarType(param_type, target);
1175 try temp_params.append(typeToValtype(scalar_type, target));
1183 const scalar_type = abi.scalarType(param_type, mod);
1184 try temp_params.append(typeToValtype(scalar_type, mod));
11761185 } else {
1177 try temp_params.append(typeToValtype(param_type, target));
1186 try temp_params.append(typeToValtype(param_type, mod));
11781187 }
11791188 }
11801189 },
1181 else => if (isByRef(param_type, target))
1190 else => if (isByRef(param_type, mod))
11821191 try temp_params.append(.i32)
11831192 else
1184 try temp_params.append(typeToValtype(param_type, target)),
1193 try temp_params.append(typeToValtype(param_type, mod)),
11851194 }
11861195 }
11871196
......@@ -1194,20 +1203,22 @@ fn genFunctype(gpa: Allocator, cc: std.builtin.CallingConvention, params: []cons
11941203pub fn generate(
11951204 bin_file: *link.File,
11961205 src_loc: Module.SrcLoc,
1197 func: *Module.Fn,
1206 func_index: Module.Fn.Index,
11981207 air: Air,
11991208 liveness: Liveness,
12001209 code: *std.ArrayList(u8),
12011210 debug_output: codegen.DebugInfoOutput,
12021211) codegen.CodeGenError!codegen.Result {
12031212 _ = src_loc;
1213 const mod = bin_file.options.module.?;
1214 const func = mod.funcPtr(func_index);
12041215 var code_gen: CodeGen = .{
12051216 .gpa = bin_file.allocator,
12061217 .air = air,
12071218 .liveness = liveness,
12081219 .code = code,
12091220 .decl_index = func.owner_decl,
1210 .decl = bin_file.options.module.?.declPtr(func.owner_decl),
1221 .decl = mod.declPtr(func.owner_decl),
12111222 .err_msg = undefined,
12121223 .locals = .{},
12131224 .target = bin_file.options.target,
......@@ -1226,8 +1237,9 @@ pub fn generate(
12261237}
12271238
12281239fn genFunc(func: *CodeGen) InnerError!void {
1229 const fn_info = func.decl.ty.fnInfo();
1230 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, func.target);
1240 const mod = func.bin_file.base.options.module.?;
1241 const fn_info = mod.typeToFunc(func.decl.ty).?;
1242 var func_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
12311243 defer func_type.deinit(func.gpa);
12321244 _ = try func.bin_file.storeDeclType(func.decl_index, func_type);
12331245
......@@ -1253,8 +1265,8 @@ fn genFunc(func: *CodeGen) InnerError!void {
12531265 // we emit an unreachable instruction to tell the stack validator that part will never be reached.
12541266 if (func_type.returns.len != 0 and func.air.instructions.len > 0) {
12551267 const inst = @intCast(u32, func.air.instructions.len - 1);
1256 const last_inst_ty = func.air.typeOfIndex(inst);
1257 if (!last_inst_ty.hasRuntimeBitsIgnoreComptime() or last_inst_ty.isNoReturn()) {
1268 const last_inst_ty = func.typeOfIndex(inst);
1269 if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(mod) or last_inst_ty.isNoReturn(mod)) {
12581270 try func.addTag(.@"unreachable");
12591271 }
12601272 }
......@@ -1335,10 +1347,9 @@ const CallWValues = struct {
13351347};
13361348
13371349fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWValues {
1338 const cc = fn_ty.fnCallingConvention();
1339 const param_types = try func.gpa.alloc(Type, fn_ty.fnParamLen());
1340 defer func.gpa.free(param_types);
1341 fn_ty.fnParamTypes(param_types);
1350 const mod = func.bin_file.base.options.module.?;
1351 const fn_info = mod.typeToFunc(fn_ty).?;
1352 const cc = fn_info.cc;
13421353 var result: CallWValues = .{
13431354 .args = &.{},
13441355 .return_value = .none,
......@@ -1350,8 +1361,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13501361
13511362 // Check if we store the result as a pointer to the stack rather than
13521363 // by value
1353 const fn_info = fn_ty.fnInfo();
1354 if (firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) {
1364 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
13551365 // the sret arg will be passed as first argument, therefore we
13561366 // set the `return_value` before allocating locals for regular args.
13571367 result.return_value = .{ .local = .{ .value = func.local_index, .references = 1 } };
......@@ -1360,8 +1370,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13601370
13611371 switch (cc) {
13621372 .Unspecified => {
1363 for (param_types) |ty| {
1364 if (!ty.hasRuntimeBitsIgnoreComptime()) {
1373 for (fn_info.param_types) |ty| {
1374 if (!ty.toType().hasRuntimeBitsIgnoreComptime(mod)) {
13651375 continue;
13661376 }
13671377
......@@ -1370,8 +1380,8 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13701380 }
13711381 },
13721382 .C => {
1373 for (param_types) |ty| {
1374 const ty_classes = abi.classifyType(ty, func.target);
1383 for (fn_info.param_types) |ty| {
1384 const ty_classes = abi.classifyType(ty.toType(), mod);
13751385 for (ty_classes) |class| {
13761386 if (class == .none) continue;
13771387 try args.append(.{ .local = .{ .value = func.local_index, .references = 1 } });
......@@ -1385,11 +1395,11 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV
13851395 return result;
13861396}
13871397
1388fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, target: std.Target) bool {
1398fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, mod: *Module) bool {
13891399 switch (cc) {
1390 .Unspecified, .Inline => return isByRef(return_type, target),
1400 .Unspecified, .Inline => return isByRef(return_type, mod),
13911401 .C => {
1392 const ty_classes = abi.classifyType(return_type, target);
1402 const ty_classes = abi.classifyType(return_type, mod);
13931403 if (ty_classes[0] == .indirect) return true;
13941404 if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true;
13951405 return false;
......@@ -1405,16 +1415,17 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
14051415 return func.lowerToStack(value);
14061416 }
14071417
1408 const ty_classes = abi.classifyType(ty, func.target);
1418 const mod = func.bin_file.base.options.module.?;
1419 const ty_classes = abi.classifyType(ty, mod);
14091420 assert(ty_classes[0] != .none);
1410 switch (ty.zigTypeTag()) {
1421 switch (ty.zigTypeTag(mod)) {
14111422 .Struct, .Union => {
14121423 if (ty_classes[0] == .indirect) {
14131424 return func.lowerToStack(value);
14141425 }
14151426 assert(ty_classes[0] == .direct);
1416 const scalar_type = abi.scalarType(ty, func.target);
1417 const abi_size = scalar_type.abiSize(func.target);
1427 const scalar_type = abi.scalarType(ty, mod);
1428 const abi_size = scalar_type.abiSize(mod);
14181429 try func.emitWValue(value);
14191430
14201431 // When the value lives in the virtual stack, we must load it onto the actual stack
......@@ -1422,12 +1433,12 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
14221433 const opcode = buildOpcode(.{
14231434 .op = .load,
14241435 .width = @intCast(u8, abi_size),
1425 .signedness = if (scalar_type.isSignedInt()) .signed else .unsigned,
1426 .valtype1 = typeToValtype(scalar_type, func.target),
1436 .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned,
1437 .valtype1 = typeToValtype(scalar_type, mod),
14271438 });
14281439 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{
14291440 .offset = value.offset(),
1430 .alignment = scalar_type.abiAlignment(func.target),
1441 .alignment = scalar_type.abiAlignment(mod),
14311442 });
14321443 }
14331444 },
......@@ -1436,7 +1447,7 @@ fn lowerArg(func: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value:
14361447 return func.lowerToStack(value);
14371448 }
14381449 assert(ty_classes[0] == .direct and ty_classes[1] == .direct);
1439 assert(ty.abiSize(func.target) == 16);
1450 assert(ty.abiSize(mod) == 16);
14401451 // in this case we have an integer or float that must be lowered as 2 i64's.
14411452 try func.emitWValue(value);
14421453 try func.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 });
......@@ -1503,18 +1514,18 @@ fn restoreStackPointer(func: *CodeGen) !void {
15031514///
15041515/// Asserts Type has codegenbits
15051516fn allocStack(func: *CodeGen, ty: Type) !WValue {
1506 assert(ty.hasRuntimeBitsIgnoreComptime());
1517 const mod = func.bin_file.base.options.module.?;
1518 assert(ty.hasRuntimeBitsIgnoreComptime(mod));
15071519 if (func.initial_stack_value == .none) {
15081520 try func.initializeStack();
15091521 }
15101522
1511 const abi_size = std.math.cast(u32, ty.abiSize(func.target)) orelse {
1512 const module = func.bin_file.base.options.module.?;
1523 const abi_size = std.math.cast(u32, ty.abiSize(mod)) orelse {
15131524 return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{
1514 ty.fmt(module), ty.abiSize(func.target),
1525 ty.fmt(mod), ty.abiSize(mod),
15151526 });
15161527 };
1517 const abi_align = ty.abiAlignment(func.target);
1528 const abi_align = ty.abiAlignment(mod);
15181529
15191530 if (abi_align > func.stack_alignment) {
15201531 func.stack_alignment = abi_align;
......@@ -1531,22 +1542,22 @@ fn allocStack(func: *CodeGen, ty: Type) !WValue {
15311542/// This is different from allocStack where this will use the pointer's alignment
15321543/// if it is set, to ensure the stack alignment will be set correctly.
15331544fn allocStackPtr(func: *CodeGen, inst: Air.Inst.Index) !WValue {
1534 const ptr_ty = func.air.typeOfIndex(inst);
1535 const pointee_ty = ptr_ty.childType();
1545 const mod = func.bin_file.base.options.module.?;
1546 const ptr_ty = func.typeOfIndex(inst);
1547 const pointee_ty = ptr_ty.childType(mod);
15361548
15371549 if (func.initial_stack_value == .none) {
15381550 try func.initializeStack();
15391551 }
15401552
1541 if (!pointee_ty.hasRuntimeBitsIgnoreComptime()) {
1553 if (!pointee_ty.hasRuntimeBitsIgnoreComptime(mod)) {
15421554 return func.allocStack(Type.usize); // create a value containing just the stack pointer.
15431555 }
15441556
1545 const abi_alignment = ptr_ty.ptrAlignment(func.target);
1546 const abi_size = std.math.cast(u32, pointee_ty.abiSize(func.target)) orelse {
1547 const module = func.bin_file.base.options.module.?;
1557 const abi_alignment = ptr_ty.ptrAlignment(mod);
1558 const abi_size = std.math.cast(u32, pointee_ty.abiSize(mod)) orelse {
15481559 return func.fail("Type {} with ABI size of {d} exceeds stack frame size", .{
1549 pointee_ty.fmt(module), pointee_ty.abiSize(func.target),
1560 pointee_ty.fmt(mod), pointee_ty.abiSize(mod),
15501561 });
15511562 };
15521563 if (abi_alignment > func.stack_alignment) {
......@@ -1704,8 +1715,9 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch {
17041715
17051716/// For a given `Type`, will return true when the type will be passed
17061717/// by reference, rather than by value
1707fn isByRef(ty: Type, target: std.Target) bool {
1708 switch (ty.zigTypeTag()) {
1718fn isByRef(ty: Type, mod: *Module) bool {
1719 const target = mod.getTarget();
1720 switch (ty.zigTypeTag(mod)) {
17091721 .Type,
17101722 .ComptimeInt,
17111723 .ComptimeFloat,
......@@ -1726,44 +1738,42 @@ fn isByRef(ty: Type, target: std.Target) bool {
17261738
17271739 .Array,
17281740 .Frame,
1729 => return ty.hasRuntimeBitsIgnoreComptime(),
1741 => return ty.hasRuntimeBitsIgnoreComptime(mod),
17301742 .Union => {
1731 if (ty.castTag(.@"union")) |union_ty| {
1732 if (union_ty.data.layout == .Packed) {
1733 return ty.abiSize(target) > 8;
1743 if (mod.typeToUnion(ty)) |union_obj| {
1744 if (union_obj.layout == .Packed) {
1745 return ty.abiSize(mod) > 8;
17341746 }
17351747 }
1736 return ty.hasRuntimeBitsIgnoreComptime();
1748 return ty.hasRuntimeBitsIgnoreComptime(mod);
17371749 },
17381750 .Struct => {
1739 if (ty.castTag(.@"struct")) |struct_ty| {
1740 const struct_obj = struct_ty.data;
1751 if (mod.typeToStruct(ty)) |struct_obj| {
17411752 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
1742 return isByRef(struct_obj.backing_int_ty, target);
1753 return isByRef(struct_obj.backing_int_ty, mod);
17431754 }
17441755 }
1745 return ty.hasRuntimeBitsIgnoreComptime();
1756 return ty.hasRuntimeBitsIgnoreComptime(mod);
17461757 },
1747 .Vector => return determineSimdStoreStrategy(ty, target) == .unrolled,
1748 .Int => return ty.intInfo(target).bits > 64,
1758 .Vector => return determineSimdStoreStrategy(ty, mod) == .unrolled,
1759 .Int => return ty.intInfo(mod).bits > 64,
17491760 .Float => return ty.floatBits(target) > 64,
17501761 .ErrorUnion => {
1751 const pl_ty = ty.errorUnionPayload();
1752 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
1762 const pl_ty = ty.errorUnionPayload(mod);
1763 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
17531764 return false;
17541765 }
17551766 return true;
17561767 },
17571768 .Optional => {
1758 if (ty.isPtrLikeOptional()) return false;
1759 var buf: Type.Payload.ElemType = undefined;
1760 const pl_type = ty.optionalChild(&buf);
1761 if (pl_type.zigTypeTag() == .ErrorSet) return false;
1762 return pl_type.hasRuntimeBitsIgnoreComptime();
1769 if (ty.isPtrLikeOptional(mod)) return false;
1770 const pl_type = ty.optionalChild(mod);
1771 if (pl_type.zigTypeTag(mod) == .ErrorSet) return false;
1772 return pl_type.hasRuntimeBitsIgnoreComptime(mod);
17631773 },
17641774 .Pointer => {
17651775 // Slices act like struct and will be passed by reference
1766 if (ty.isSlice()) return true;
1776 if (ty.isSlice(mod)) return true;
17671777 return false;
17681778 },
17691779 }
......@@ -1778,10 +1788,11 @@ const SimdStoreStrategy = enum {
17781788/// This means when a given type is 128 bits and either the simd128 or relaxed-simd
17791789/// features are enabled, the function will return `.direct`. This would allow to store
17801790/// it using a instruction, rather than an unrolled version.
1781fn determineSimdStoreStrategy(ty: Type, target: std.Target) SimdStoreStrategy {
1782 std.debug.assert(ty.zigTypeTag() == .Vector);
1783 if (ty.bitSize(target) != 128) return .unrolled;
1791fn determineSimdStoreStrategy(ty: Type, mod: *Module) SimdStoreStrategy {
1792 std.debug.assert(ty.zigTypeTag(mod) == .Vector);
1793 if (ty.bitSize(mod) != 128) return .unrolled;
17841794 const hasFeature = std.Target.wasm.featureSetHas;
1795 const target = mod.getTarget();
17851796 const features = target.cpu.features;
17861797 if (hasFeature(features, .relaxed_simd) or hasFeature(features, .simd128)) {
17871798 return .direct;
......@@ -1821,8 +1832,7 @@ fn buildPointerOffset(func: *CodeGen, ptr_value: WValue, offset: u64, action: en
18211832fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
18221833 const air_tags = func.air.instructions.items(.tag);
18231834 return switch (air_tags[inst]) {
1824 .constant => unreachable,
1825 .const_ty => unreachable,
1835 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
18261836
18271837 .add => func.airBinOp(inst, .add),
18281838 .add_sat => func.airSatBinOp(inst, .add),
......@@ -2062,8 +2072,11 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
20622072}
20632073
20642074fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
2075 const mod = func.bin_file.base.options.module.?;
2076 const ip = &mod.intern_pool;
2077
20652078 for (body) |inst| {
2066 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst)) {
2079 if (func.liveness.isUnused(inst) and !func.air.mustLower(inst, ip)) {
20672080 continue;
20682081 }
20692082 const old_bookkeeping_value = func.air_bookkeeping;
......@@ -2080,36 +2093,37 @@ fn genBody(func: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
20802093}
20812094
20822095fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2096 const mod = func.bin_file.base.options.module.?;
20832097 const un_op = func.air.instructions.items(.data)[inst].un_op;
20842098 const operand = try func.resolveInst(un_op);
2085 const fn_info = func.decl.ty.fnInfo();
2086 const ret_ty = fn_info.return_type;
2099 const fn_info = mod.typeToFunc(func.decl.ty).?;
2100 const ret_ty = fn_info.return_type.toType();
20872101
20882102 // result must be stored in the stack and we return a pointer
20892103 // to the stack instead
20902104 if (func.return_value != .none) {
20912105 try func.store(func.return_value, operand, ret_ty, 0);
2092 } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime()) {
2093 switch (ret_ty.zigTypeTag()) {
2106 } else if (fn_info.cc == .C and ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2107 switch (ret_ty.zigTypeTag(mod)) {
20942108 // Aggregate types can be lowered as a singular value
20952109 .Struct, .Union => {
2096 const scalar_type = abi.scalarType(ret_ty, func.target);
2110 const scalar_type = abi.scalarType(ret_ty, mod);
20972111 try func.emitWValue(operand);
20982112 const opcode = buildOpcode(.{
20992113 .op = .load,
2100 .width = @intCast(u8, scalar_type.abiSize(func.target) * 8),
2101 .signedness = if (scalar_type.isSignedInt()) .signed else .unsigned,
2102 .valtype1 = typeToValtype(scalar_type, func.target),
2114 .width = @intCast(u8, scalar_type.abiSize(mod) * 8),
2115 .signedness = if (scalar_type.isSignedInt(mod)) .signed else .unsigned,
2116 .valtype1 = typeToValtype(scalar_type, mod),
21032117 });
21042118 try func.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{
21052119 .offset = operand.offset(),
2106 .alignment = scalar_type.abiAlignment(func.target),
2120 .alignment = scalar_type.abiAlignment(mod),
21072121 });
21082122 },
21092123 else => try func.emitWValue(operand),
21102124 }
21112125 } else {
2112 if (!ret_ty.hasRuntimeBitsIgnoreComptime() and ret_ty.isError()) {
2126 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and ret_ty.isError(mod)) {
21132127 try func.addImm32(0);
21142128 } else {
21152129 try func.emitWValue(operand);
......@@ -2122,15 +2136,16 @@ fn airRet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21222136}
21232137
21242138fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2125 const child_type = func.air.typeOfIndex(inst).childType();
2139 const mod = func.bin_file.base.options.module.?;
2140 const child_type = func.typeOfIndex(inst).childType(mod);
21262141
21272142 var result = result: {
2128 if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime()) {
2143 if (!child_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
21292144 break :result try func.allocStack(Type.usize); // create pointer to void
21302145 }
21312146
2132 const fn_info = func.decl.ty.fnInfo();
2133 if (firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) {
2147 const fn_info = mod.typeToFunc(func.decl.ty).?;
2148 if (firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
21342149 break :result func.return_value;
21352150 }
21362151
......@@ -2141,16 +2156,17 @@ fn airRetPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
21412156}
21422157
21432158fn airRetLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2159 const mod = func.bin_file.base.options.module.?;
21442160 const un_op = func.air.instructions.items(.data)[inst].un_op;
21452161 const operand = try func.resolveInst(un_op);
2146 const ret_ty = func.air.typeOf(un_op).childType();
2162 const ret_ty = func.typeOf(un_op).childType(mod);
21472163
2148 const fn_info = func.decl.ty.fnInfo();
2149 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
2150 if (ret_ty.isError()) {
2164 const fn_info = mod.typeToFunc(func.decl.ty).?;
2165 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2166 if (ret_ty.isError(mod)) {
21512167 try func.addImm32(0);
21522168 }
2153 } else if (!firstParamSRet(fn_info.cc, fn_info.return_type, func.target)) {
2169 } else if (!firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod)) {
21542170 // leave on the stack
21552171 _ = try func.load(operand, ret_ty, 0);
21562172 }
......@@ -2165,42 +2181,48 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
21652181 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
21662182 const extra = func.air.extraData(Air.Call, pl_op.payload);
21672183 const args = @ptrCast([]const Air.Inst.Ref, func.air.extra[extra.end..][0..extra.data.args_len]);
2168 const ty = func.air.typeOf(pl_op.operand);
2184 const ty = func.typeOf(pl_op.operand);
21692185
2170 const fn_ty = switch (ty.zigTypeTag()) {
2186 const mod = func.bin_file.base.options.module.?;
2187 const fn_ty = switch (ty.zigTypeTag(mod)) {
21712188 .Fn => ty,
2172 .Pointer => ty.childType(),
2189 .Pointer => ty.childType(mod),
21732190 else => unreachable,
21742191 };
2175 const ret_ty = fn_ty.fnReturnType();
2176 const fn_info = fn_ty.fnInfo();
2177 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, func.target);
2192 const ret_ty = fn_ty.fnReturnType(mod);
2193 const fn_info = mod.typeToFunc(fn_ty).?;
2194 const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type.toType(), mod);
21782195
21792196 const callee: ?Decl.Index = blk: {
2180 const func_val = func.air.value(pl_op.operand) orelse break :blk null;
2181 const module = func.bin_file.base.options.module.?;
2182
2183 if (func_val.castTag(.function)) |function| {
2184 _ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);
2185 break :blk function.data.owner_decl;
2186 } else if (func_val.castTag(.extern_fn)) |extern_fn| {
2187 const ext_decl = module.declPtr(extern_fn.data.owner_decl);
2188 const ext_info = ext_decl.ty.fnInfo();
2189 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type, func.target);
2197 const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;
2198
2199 if (func_val.getFunction(mod)) |function| {
2200 _ = try func.bin_file.getOrCreateAtomForDecl(function.owner_decl);
2201 break :blk function.owner_decl;
2202 } else if (func_val.getExternFunc(mod)) |extern_func| {
2203 const ext_decl = mod.declPtr(extern_func.decl);
2204 const ext_info = mod.typeToFunc(ext_decl.ty).?;
2205 var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types, ext_info.return_type.toType(), mod);
21902206 defer func_type.deinit(func.gpa);
2191 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_fn.data.owner_decl);
2207 const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
21922208 const atom = func.bin_file.getAtomPtr(atom_index);
2193 const type_index = try func.bin_file.storeDeclType(extern_fn.data.owner_decl, func_type);
2209 const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type);
21942210 try func.bin_file.addOrUpdateImport(
2195 mem.sliceTo(ext_decl.name, 0),
2211 mod.intern_pool.stringToSlice(ext_decl.name),
21962212 atom.getSymbolIndex().?,
2197 ext_decl.getExternFn().?.lib_name,
2213 mod.intern_pool.stringToSliceUnwrap(ext_decl.getOwnedExternFunc(mod).?.lib_name),
21982214 type_index,
21992215 );
2200 break :blk extern_fn.data.owner_decl;
2201 } else if (func_val.castTag(.decl_ref)) |decl_ref| {
2202 _ = try func.bin_file.getOrCreateAtomForDecl(decl_ref.data);
2203 break :blk decl_ref.data;
2216 break :blk extern_func.decl;
2217 } else switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
2218 .ptr => |ptr| switch (ptr.addr) {
2219 .decl => |decl| {
2220 _ = try func.bin_file.getOrCreateAtomForDecl(decl);
2221 break :blk decl;
2222 },
2223 else => {},
2224 },
2225 else => {},
22042226 }
22052227 return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()});
22062228 };
......@@ -2214,10 +2236,10 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22142236 for (args) |arg| {
22152237 const arg_val = try func.resolveInst(arg);
22162238
2217 const arg_ty = func.air.typeOf(arg);
2218 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;
2239 const arg_ty = func.typeOf(arg);
2240 if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22192241
2220 try func.lowerArg(fn_ty.fnInfo().cc, arg_ty, arg_val);
2242 try func.lowerArg(mod.typeToFunc(fn_ty).?.cc, arg_ty, arg_val);
22212243 }
22222244
22232245 if (callee) |direct| {
......@@ -2226,11 +2248,11 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22262248 } else {
22272249 // in this case we call a function pointer
22282250 // so load its value onto the stack
2229 std.debug.assert(ty.zigTypeTag() == .Pointer);
2251 std.debug.assert(ty.zigTypeTag(mod) == .Pointer);
22302252 const operand = try func.resolveInst(pl_op.operand);
22312253 try func.emitWValue(operand);
22322254
2233 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type, func.target);
2255 var fn_type = try genFunctype(func.gpa, fn_info.cc, fn_info.param_types, fn_info.return_type.toType(), mod);
22342256 defer fn_type.deinit(func.gpa);
22352257
22362258 const fn_type_index = try func.bin_file.putOrGetFuncType(fn_type);
......@@ -2238,18 +2260,18 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
22382260 }
22392261
22402262 const result_value = result_value: {
2241 if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
2263 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod) and !ret_ty.isError(mod)) {
22422264 break :result_value WValue{ .none = {} };
2243 } else if (ret_ty.isNoReturn()) {
2265 } else if (ret_ty.isNoReturn(mod)) {
22442266 try func.addTag(.@"unreachable");
22452267 break :result_value WValue{ .none = {} };
22462268 } else if (first_param_sret) {
22472269 break :result_value sret;
22482270 // TODO: Make this less fragile and optimize
2249 } else if (fn_ty.fnInfo().cc == .C and ret_ty.zigTypeTag() == .Struct or ret_ty.zigTypeTag() == .Union) {
2271 } else if (mod.typeToFunc(fn_ty).?.cc == .C and ret_ty.zigTypeTag(mod) == .Struct or ret_ty.zigTypeTag(mod) == .Union) {
22502272 const result_local = try func.allocLocal(ret_ty);
22512273 try func.addLabel(.local_set, result_local.local.value);
2252 const scalar_type = abi.scalarType(ret_ty, func.target);
2274 const scalar_type = abi.scalarType(ret_ty, mod);
22532275 const result = try func.allocStack(scalar_type);
22542276 try func.store(result, result_local, scalar_type, 0);
22552277 break :result_value result;
......@@ -2272,6 +2294,7 @@ fn airAlloc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
22722294}
22732295
22742296fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
2297 const mod = func.bin_file.base.options.module.?;
22752298 if (safety) {
22762299 // TODO if the value is undef, write 0xaa bytes to dest
22772300 } else {
......@@ -2281,26 +2304,22 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
22812304
22822305 const lhs = try func.resolveInst(bin_op.lhs);
22832306 const rhs = try func.resolveInst(bin_op.rhs);
2284 const ptr_ty = func.air.typeOf(bin_op.lhs);
2285 const ptr_info = ptr_ty.ptrInfo().data;
2286 const ty = ptr_ty.childType();
2307 const ptr_ty = func.typeOf(bin_op.lhs);
2308 const ptr_info = ptr_ty.ptrInfo(mod);
2309 const ty = ptr_ty.childType(mod);
22872310
22882311 if (ptr_info.host_size == 0) {
22892312 try func.store(lhs, rhs, ty, 0);
22902313 } else {
22912314 // at this point we have a non-natural alignment, we must
22922315 // load the value, and then shift+or the rhs into the result location.
2293 var int_ty_payload: Type.Payload.Bits = .{
2294 .base = .{ .tag = .int_unsigned },
2295 .data = ptr_info.host_size * 8,
2296 };
2297 const int_elem_ty = Type.initPayload(&int_ty_payload.base);
2316 const int_elem_ty = try mod.intType(.unsigned, ptr_info.host_size * 8);
22982317
2299 if (isByRef(int_elem_ty, func.target)) {
2318 if (isByRef(int_elem_ty, mod)) {
23002319 return func.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{});
23012320 }
23022321
2303 var mask = @intCast(u64, (@as(u65, 1) << @intCast(u7, ty.bitSize(func.target))) - 1);
2322 var mask = @intCast(u64, (@as(u65, 1) << @intCast(u7, ty.bitSize(mod))) - 1);
23042323 mask <<= @intCast(u6, ptr_info.bit_offset);
23052324 mask ^= ~@as(u64, 0);
23062325 const shift_val = if (ptr_info.host_size <= 4)
......@@ -2329,11 +2348,12 @@ fn airStore(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
23292348
23302349fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void {
23312350 assert(!(lhs != .stack and rhs == .stack));
2332 const abi_size = ty.abiSize(func.target);
2333 switch (ty.zigTypeTag()) {
2351 const mod = func.bin_file.base.options.module.?;
2352 const abi_size = ty.abiSize(mod);
2353 switch (ty.zigTypeTag(mod)) {
23342354 .ErrorUnion => {
2335 const pl_ty = ty.errorUnionPayload();
2336 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
2355 const pl_ty = ty.errorUnionPayload(mod);
2356 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
23372357 return func.store(lhs, rhs, Type.anyerror, 0);
23382358 }
23392359
......@@ -2341,26 +2361,25 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
23412361 return func.memcpy(lhs, rhs, .{ .imm32 = len });
23422362 },
23432363 .Optional => {
2344 if (ty.isPtrLikeOptional()) {
2364 if (ty.isPtrLikeOptional(mod)) {
23452365 return func.store(lhs, rhs, Type.usize, 0);
23462366 }
2347 var buf: Type.Payload.ElemType = undefined;
2348 const pl_ty = ty.optionalChild(&buf);
2349 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
2367 const pl_ty = ty.optionalChild(mod);
2368 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
23502369 return func.store(lhs, rhs, Type.u8, 0);
23512370 }
2352 if (pl_ty.zigTypeTag() == .ErrorSet) {
2371 if (pl_ty.zigTypeTag(mod) == .ErrorSet) {
23532372 return func.store(lhs, rhs, Type.anyerror, 0);
23542373 }
23552374
23562375 const len = @intCast(u32, abi_size);
23572376 return func.memcpy(lhs, rhs, .{ .imm32 = len });
23582377 },
2359 .Struct, .Array, .Union => if (isByRef(ty, func.target)) {
2378 .Struct, .Array, .Union => if (isByRef(ty, mod)) {
23602379 const len = @intCast(u32, abi_size);
23612380 return func.memcpy(lhs, rhs, .{ .imm32 = len });
23622381 },
2363 .Vector => switch (determineSimdStoreStrategy(ty, func.target)) {
2382 .Vector => switch (determineSimdStoreStrategy(ty, mod)) {
23642383 .unrolled => {
23652384 const len = @intCast(u32, abi_size);
23662385 return func.memcpy(lhs, rhs, .{ .imm32 = len });
......@@ -2374,13 +2393,13 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
23742393 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
23752394 std.wasm.simdOpcode(.v128_store),
23762395 offset + lhs.offset(),
2377 ty.abiAlignment(func.target),
2396 ty.abiAlignment(mod),
23782397 });
23792398 return func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
23802399 },
23812400 },
23822401 .Pointer => {
2383 if (ty.isSlice()) {
2402 if (ty.isSlice(mod)) {
23842403 // store pointer first
23852404 // lower it to the stack so we do not have to store rhs into a local first
23862405 try func.emitWValue(lhs);
......@@ -2404,7 +2423,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
24042423 try func.store(.{ .stack = {} }, msb, Type.u64, 8 + lhs.offset());
24052424 return;
24062425 } else if (abi_size > 16) {
2407 try func.memcpy(lhs, rhs, .{ .imm32 = @intCast(u32, ty.abiSize(func.target)) });
2426 try func.memcpy(lhs, rhs, .{ .imm32 = @intCast(u32, ty.abiSize(mod)) });
24082427 },
24092428 else => if (abi_size > 8) {
24102429 return func.fail("TODO: `store` for type `{}` with abisize `{d}`", .{
......@@ -2418,7 +2437,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
24182437 // into lhs, so we calculate that and emit that instead
24192438 try func.lowerToStack(rhs);
24202439
2421 const valtype = typeToValtype(ty, func.target);
2440 const valtype = typeToValtype(ty, mod);
24222441 const opcode = buildOpcode(.{
24232442 .valtype1 = valtype,
24242443 .width = @intCast(u8, abi_size * 8),
......@@ -2428,21 +2447,22 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE
24282447 // store rhs value at stack pointer's location in memory
24292448 try func.addMemArg(
24302449 Mir.Inst.Tag.fromOpcode(opcode),
2431 .{ .offset = offset + lhs.offset(), .alignment = ty.abiAlignment(func.target) },
2450 .{ .offset = offset + lhs.offset(), .alignment = ty.abiAlignment(mod) },
24322451 );
24332452}
24342453
24352454fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2455 const mod = func.bin_file.base.options.module.?;
24362456 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
24372457 const operand = try func.resolveInst(ty_op.operand);
24382458 const ty = func.air.getRefType(ty_op.ty);
2439 const ptr_ty = func.air.typeOf(ty_op.operand);
2440 const ptr_info = ptr_ty.ptrInfo().data;
2459 const ptr_ty = func.typeOf(ty_op.operand);
2460 const ptr_info = ptr_ty.ptrInfo(mod);
24412461
2442 if (!ty.hasRuntimeBitsIgnoreComptime()) return func.finishAir(inst, .none, &.{ty_op.operand});
2462 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{ty_op.operand});
24432463
24442464 const result = result: {
2445 if (isByRef(ty, func.target)) {
2465 if (isByRef(ty, mod)) {
24462466 const new_local = try func.allocStack(ty);
24472467 try func.store(new_local, operand, ty, 0);
24482468 break :result new_local;
......@@ -2455,11 +2475,7 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24552475
24562476 // at this point we have a non-natural alignment, we must
24572477 // shift the value to obtain the correct bit.
2458 var int_ty_payload: Type.Payload.Bits = .{
2459 .base = .{ .tag = .int_unsigned },
2460 .data = ptr_info.host_size * 8,
2461 };
2462 const int_elem_ty = Type.initPayload(&int_ty_payload.base);
2478 const int_elem_ty = try mod.intType(.unsigned, ptr_info.host_size * 8);
24632479 const shift_val = if (ptr_info.host_size <= 4)
24642480 WValue{ .imm32 = ptr_info.bit_offset }
24652481 else if (ptr_info.host_size <= 8)
......@@ -2479,25 +2495,26 @@ fn airLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
24792495/// Loads an operand from the linear memory section.
24802496/// NOTE: Leaves the value on the stack.
24812497fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue {
2498 const mod = func.bin_file.base.options.module.?;
24822499 // load local's value from memory by its stack position
24832500 try func.emitWValue(operand);
24842501
2485 if (ty.zigTypeTag() == .Vector) {
2502 if (ty.zigTypeTag(mod) == .Vector) {
24862503 // TODO: Add helper functions for simd opcodes
24872504 const extra_index = @intCast(u32, func.mir_extra.items.len);
24882505 // stores as := opcode, offset, alignment (opcode::memarg)
24892506 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
24902507 std.wasm.simdOpcode(.v128_load),
24912508 offset + operand.offset(),
2492 ty.abiAlignment(func.target),
2509 ty.abiAlignment(mod),
24932510 });
24942511 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
24952512 return WValue{ .stack = {} };
24962513 }
24972514
2498 const abi_size = @intCast(u8, ty.abiSize(func.target));
2515 const abi_size = @intCast(u8, ty.abiSize(mod));
24992516 const opcode = buildOpcode(.{
2500 .valtype1 = typeToValtype(ty, func.target),
2517 .valtype1 = typeToValtype(ty, mod),
25012518 .width = abi_size * 8,
25022519 .op = .load,
25032520 .signedness = .unsigned,
......@@ -2505,19 +2522,20 @@ fn load(func: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValu
25052522
25062523 try func.addMemArg(
25072524 Mir.Inst.Tag.fromOpcode(opcode),
2508 .{ .offset = offset + operand.offset(), .alignment = ty.abiAlignment(func.target) },
2525 .{ .offset = offset + operand.offset(), .alignment = ty.abiAlignment(mod) },
25092526 );
25102527
25112528 return WValue{ .stack = {} };
25122529}
25132530
25142531fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
2532 const mod = func.bin_file.base.options.module.?;
25152533 const arg_index = func.arg_index;
25162534 const arg = func.args[arg_index];
2517 const cc = func.decl.ty.fnInfo().cc;
2518 const arg_ty = func.air.typeOfIndex(inst);
2535 const cc = mod.typeToFunc(func.decl.ty).?.cc;
2536 const arg_ty = func.typeOfIndex(inst);
25192537 if (cc == .C) {
2520 const arg_classes = abi.classifyType(arg_ty, func.target);
2538 const arg_classes = abi.classifyType(arg_ty, mod);
25212539 for (arg_classes) |class| {
25222540 if (class != .none) {
25232541 func.arg_index += 1;
......@@ -2527,7 +2545,7 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25272545 // When we have an argument that's passed using more than a single parameter,
25282546 // we combine them into a single stack value
25292547 if (arg_classes[0] == .direct and arg_classes[1] == .direct) {
2530 if (arg_ty.zigTypeTag() != .Int and arg_ty.zigTypeTag() != .Float) {
2548 if (arg_ty.zigTypeTag(mod) != .Int and arg_ty.zigTypeTag(mod) != .Float) {
25312549 return func.fail(
25322550 "TODO: Implement C-ABI argument for type '{}'",
25332551 .{arg_ty.fmt(func.bin_file.base.options.module.?)},
......@@ -2557,11 +2575,12 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
25572575}
25582576
25592577fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2578 const mod = func.bin_file.base.options.module.?;
25602579 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
25612580 const lhs = try func.resolveInst(bin_op.lhs);
25622581 const rhs = try func.resolveInst(bin_op.rhs);
2563 const lhs_ty = func.air.typeOf(bin_op.lhs);
2564 const rhs_ty = func.air.typeOf(bin_op.rhs);
2582 const lhs_ty = func.typeOf(bin_op.lhs);
2583 const rhs_ty = func.typeOf(bin_op.rhs);
25652584
25662585 // For certain operations, such as shifting, the types are different.
25672586 // When converting this to a WebAssembly type, they *must* match to perform
......@@ -2570,10 +2589,10 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
25702589 // For big integers we can ignore this as we will call into compiler-rt which handles this.
25712590 const result = switch (op) {
25722591 .shr, .shl => res: {
2573 const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(func.target))) orelse {
2592 const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(mod))) orelse {
25742593 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
25752594 };
2576 const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(func.target))).?;
2595 const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(mod))).?;
25772596 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {
25782597 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);
25792598 break :blk try tmp.toLocal(func, lhs_ty);
......@@ -2593,6 +2612,7 @@ fn airBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
25932612/// Performs a binary operation on the given `WValue`'s
25942613/// NOTE: THis leaves the value on top of the stack.
25952614fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {
2615 const mod = func.bin_file.base.options.module.?;
25962616 assert(!(lhs != .stack and rhs == .stack));
25972617
25982618 if (ty.isAnyFloat()) {
......@@ -2600,8 +2620,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
26002620 return func.floatOp(float_op, ty, &.{ lhs, rhs });
26012621 }
26022622
2603 if (isByRef(ty, func.target)) {
2604 if (ty.zigTypeTag() == .Int) {
2623 if (isByRef(ty, mod)) {
2624 if (ty.zigTypeTag(mod) == .Int) {
26052625 return func.binOpBigInt(lhs, rhs, ty, op);
26062626 } else {
26072627 return func.fail(
......@@ -2613,8 +2633,8 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
26132633
26142634 const opcode: wasm.Opcode = buildOpcode(.{
26152635 .op = op,
2616 .valtype1 = typeToValtype(ty, func.target),
2617 .signedness = if (ty.isSignedInt()) .signed else .unsigned,
2636 .valtype1 = typeToValtype(ty, mod),
2637 .signedness = if (ty.isSignedInt(mod)) .signed else .unsigned,
26182638 });
26192639 try func.emitWValue(lhs);
26202640 try func.emitWValue(rhs);
......@@ -2625,14 +2645,15 @@ fn binOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!
26252645}
26262646
26272647fn binOpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WValue {
2628 if (ty.intInfo(func.target).bits > 128) {
2648 const mod = func.bin_file.base.options.module.?;
2649 if (ty.intInfo(mod).bits > 128) {
26292650 return func.fail("TODO: Implement binary operation for big integers larger than 128 bits", .{});
26302651 }
26312652
26322653 switch (op) {
2633 .mul => return func.callIntrinsic("__multi3", &.{ ty, ty }, ty, &.{ lhs, rhs }),
2634 .shr => return func.callIntrinsic("__lshrti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),
2635 .shl => return func.callIntrinsic("__ashlti3", &.{ ty, Type.i32 }, ty, &.{ lhs, rhs }),
2654 .mul => return func.callIntrinsic("__multi3", &.{ ty.toIntern(), ty.toIntern() }, ty, &.{ lhs, rhs }),
2655 .shr => return func.callIntrinsic("__lshrti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
2656 .shl => return func.callIntrinsic("__ashlti3", &.{ ty.toIntern(), .i32_type }, ty, &.{ lhs, rhs }),
26362657 .xor => {
26372658 const result = try func.allocStack(ty);
26382659 try func.emitWValue(result);
......@@ -2756,14 +2777,15 @@ const FloatOp = enum {
27562777fn airUnaryFloatOp(func: *CodeGen, inst: Air.Inst.Index, op: FloatOp) InnerError!void {
27572778 const un_op = func.air.instructions.items(.data)[inst].un_op;
27582779 const operand = try func.resolveInst(un_op);
2759 const ty = func.air.typeOf(un_op);
2780 const ty = func.typeOf(un_op);
27602781
27612782 const result = try (try func.floatOp(op, ty, &.{operand})).toLocal(func, ty);
27622783 func.finishAir(inst, result, &.{un_op});
27632784}
27642785
27652786fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) InnerError!WValue {
2766 if (ty.zigTypeTag() == .Vector) {
2787 const mod = func.bin_file.base.options.module.?;
2788 if (ty.zigTypeTag(mod) == .Vector) {
27672789 return func.fail("TODO: Implement floatOps for vectors", .{});
27682790 }
27692791
......@@ -2773,7 +2795,7 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
27732795 for (args) |operand| {
27742796 try func.emitWValue(operand);
27752797 }
2776 const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, func.target) });
2798 const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, mod) });
27772799 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
27782800 return .stack;
27792801 }
......@@ -2821,20 +2843,21 @@ fn floatOp(func: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) In
28212843 };
28222844
28232845 // fma requires three operands
2824 var param_types_buffer: [3]Type = .{ ty, ty, ty };
2846 var param_types_buffer: [3]InternPool.Index = .{ ty.ip_index, ty.ip_index, ty.ip_index };
28252847 const param_types = param_types_buffer[0..args.len];
28262848 return func.callIntrinsic(fn_name, param_types, ty, args);
28272849}
28282850
28292851fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
2852 const mod = func.bin_file.base.options.module.?;
28302853 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
28312854
28322855 const lhs = try func.resolveInst(bin_op.lhs);
28332856 const rhs = try func.resolveInst(bin_op.rhs);
2834 const lhs_ty = func.air.typeOf(bin_op.lhs);
2835 const rhs_ty = func.air.typeOf(bin_op.rhs);
2857 const lhs_ty = func.typeOf(bin_op.lhs);
2858 const rhs_ty = func.typeOf(bin_op.rhs);
28362859
2837 if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) {
2860 if (lhs_ty.zigTypeTag(mod) == .Vector or rhs_ty.zigTypeTag(mod) == .Vector) {
28382861 return func.fail("TODO: Implement wrapping arithmetic for vectors", .{});
28392862 }
28402863
......@@ -2845,10 +2868,10 @@ fn airWrapBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
28452868 // For big integers we can ignore this as we will call into compiler-rt which handles this.
28462869 const result = switch (op) {
28472870 .shr, .shl => res: {
2848 const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(func.target))) orelse {
2871 const lhs_wasm_bits = toWasmBits(@intCast(u16, lhs_ty.bitSize(mod))) orelse {
28492872 return func.fail("TODO: implement '{s}' for types larger than 128 bits", .{@tagName(op)});
28502873 };
2851 const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(func.target))).?;
2874 const rhs_wasm_bits = toWasmBits(@intCast(u16, rhs_ty.bitSize(mod))).?;
28522875 const new_rhs = if (lhs_wasm_bits != rhs_wasm_bits and lhs_wasm_bits != 128) blk: {
28532876 const tmp = try func.intcast(rhs, rhs_ty, lhs_ty);
28542877 break :blk try tmp.toLocal(func, lhs_ty);
......@@ -2877,8 +2900,9 @@ fn wrapBinOp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerEr
28772900/// Asserts `Type` is <= 128 bits.
28782901/// NOTE: When the Type is <= 64 bits, leaves the value on top of the stack.
28792902fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
2880 assert(ty.abiSize(func.target) <= 16);
2881 const bitsize = @intCast(u16, ty.bitSize(func.target));
2903 const mod = func.bin_file.base.options.module.?;
2904 assert(ty.abiSize(mod) <= 16);
2905 const bitsize = @intCast(u16, ty.bitSize(mod));
28822906 const wasm_bits = toWasmBits(bitsize) orelse {
28832907 return func.fail("TODO: Implement wrapOperand for bitsize '{d}'", .{bitsize});
28842908 };
......@@ -2914,43 +2938,67 @@ fn wrapOperand(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
29142938 return WValue{ .stack = {} };
29152939}
29162940
2917fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue {
2918 switch (ptr_val.tag()) {
2919 .decl_ref_mut => {
2920 const decl_index = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;
2921 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
2941fn lowerParentPtr(func: *CodeGen, ptr_val: Value) InnerError!WValue {
2942 const mod = func.bin_file.base.options.module.?;
2943 const ptr = mod.intern_pool.indexToKey(ptr_val.ip_index).ptr;
2944 switch (ptr.addr) {
2945 .decl => |decl_index| {
2946 return func.lowerParentPtrDecl(ptr_val, decl_index, 0);
2947 },
2948 .mut_decl => |mut_decl| {
2949 const decl_index = mut_decl.decl;
2950 return func.lowerParentPtrDecl(ptr_val, decl_index, 0);
29222951 },
2923 .decl_ref => {
2924 const decl_index = ptr_val.castTag(.decl_ref).?.data;
2925 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
2952 .int, .eu_payload => |tag| return func.fail("TODO: Implement lowerParentPtr for {}", .{tag}),
2953 .opt_payload => |base_ptr| {
2954 return func.lowerParentPtr(base_ptr.toValue());
29262955 },
2927 .variable => {
2928 const decl_index = ptr_val.castTag(.variable).?.data.owner_decl;
2929 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
2956 .comptime_field => unreachable,
2957 .elem => |elem| {
2958 const index = elem.index;
2959 const elem_type = mod.intern_pool.typeOf(elem.base).toType().elemType2(mod);
2960 const offset = index * elem_type.abiSize(mod);
2961 const array_ptr = try func.lowerParentPtr(elem.base.toValue());
2962
2963 return switch (array_ptr) {
2964 .memory => |ptr_| WValue{
2965 .memory_offset = .{
2966 .pointer = ptr_,
2967 .offset = @intCast(u32, offset),
2968 },
2969 },
2970 .memory_offset => |mem_off| WValue{
2971 .memory_offset = .{
2972 .pointer = mem_off.pointer,
2973 .offset = @intCast(u32, offset) + mem_off.offset,
2974 },
2975 },
2976 else => unreachable,
2977 };
29302978 },
2931 .field_ptr => {
2932 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
2933 const parent_ty = field_ptr.container_ty;
2934
2935 const field_offset = switch (parent_ty.zigTypeTag()) {
2936 .Struct => switch (parent_ty.containerLayout()) {
2937 .Packed => parent_ty.packedStructFieldByteOffset(field_ptr.field_index, func.target),
2938 else => parent_ty.structFieldOffset(field_ptr.field_index, func.target),
2979 .field => |field| {
2980 const parent_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
2981 const parent_ptr = try func.lowerParentPtr(field.base.toValue());
2982
2983 const offset = switch (parent_ty.zigTypeTag(mod)) {
2984 .Struct => switch (parent_ty.containerLayout(mod)) {
2985 .Packed => parent_ty.packedStructFieldByteOffset(@intCast(usize, field.index), mod),
2986 else => parent_ty.structFieldOffset(@intCast(usize, field.index), mod),
29392987 },
2940 .Union => switch (parent_ty.containerLayout()) {
2988 .Union => switch (parent_ty.containerLayout(mod)) {
29412989 .Packed => 0,
29422990 else => blk: {
2943 const layout: Module.Union.Layout = parent_ty.unionGetLayout(func.target);
2991 const layout: Module.Union.Layout = parent_ty.unionGetLayout(mod);
29442992 if (layout.payload_size == 0) break :blk 0;
29452993 if (layout.payload_align > layout.tag_align) break :blk 0;
29462994
29472995 // tag is stored first so calculate offset from where payload starts
2948 const field_offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
2949 break :blk field_offset;
2996 const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
2997 break :blk offset;
29502998 },
29512999 },
2952 .Pointer => switch (parent_ty.ptrSize()) {
2953 .Slice => switch (field_ptr.field_index) {
3000 .Pointer => switch (parent_ty.ptrSize(mod)) {
3001 .Slice => switch (field.index) {
29543002 0 => 0,
29553003 1 => func.ptrSize(),
29563004 else => unreachable,
......@@ -2959,51 +3007,51 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
29593007 },
29603008 else => unreachable,
29613009 };
2962 return func.lowerParentPtr(field_ptr.container_ptr, offset + @intCast(u32, field_offset));
2963 },
2964 .elem_ptr => {
2965 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2966 const index = elem_ptr.index;
2967 const elem_offset = index * elem_ptr.elem_ty.abiSize(func.target);
2968 return func.lowerParentPtr(elem_ptr.array_ptr, offset + @intCast(u32, elem_offset));
2969 },
2970 .opt_payload_ptr => {
2971 const payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
2972 return func.lowerParentPtr(payload_ptr.container_ptr, offset);
3010
3011 return switch (parent_ptr) {
3012 .memory => |ptr_| WValue{
3013 .memory_offset = .{
3014 .pointer = ptr_,
3015 .offset = @intCast(u32, offset),
3016 },
3017 },
3018 .memory_offset => |mem_off| WValue{
3019 .memory_offset = .{
3020 .pointer = mem_off.pointer,
3021 .offset = @intCast(u32, offset) + mem_off.offset,
3022 },
3023 },
3024 else => unreachable,
3025 };
29733026 },
2974 else => |tag| return func.fail("TODO: Implement lowerParentPtr for tag: {}", .{tag}),
29753027 }
29763028}
29773029
29783030fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {
2979 const module = func.bin_file.base.options.module.?;
2980 const decl = module.declPtr(decl_index);
2981 module.markDeclAlive(decl);
2982 var ptr_ty_payload: Type.Payload.ElemType = .{
2983 .base = .{ .tag = .single_mut_pointer },
2984 .data = decl.ty,
2985 };
2986 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
3031 const mod = func.bin_file.base.options.module.?;
3032 const decl = mod.declPtr(decl_index);
3033 try mod.markDeclAlive(decl);
3034 const ptr_ty = try mod.singleMutPtrType(decl.ty);
29873035 return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset);
29883036}
29893037
29903038fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {
2991 if (tv.ty.isSlice()) {
3039 const mod = func.bin_file.base.options.module.?;
3040 if (tv.ty.isSlice(mod)) {
29923041 return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) };
29933042 }
29943043
2995 const module = func.bin_file.base.options.module.?;
2996 const decl = module.declPtr(decl_index);
2997 if (decl.ty.zigTypeTag() != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime()) {
3044 const decl = mod.declPtr(decl_index);
3045 if (decl.ty.zigTypeTag(mod) != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime(mod)) {
29983046 return WValue{ .imm32 = 0xaaaaaaaa };
29993047 }
30003048
3001 module.markDeclAlive(decl);
3049 try mod.markDeclAlive(decl);
30023050 const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
30033051 const atom = func.bin_file.getAtom(atom_index);
30043052
30053053 const target_sym_index = atom.sym_index;
3006 if (decl.ty.zigTypeTag() == .Fn) {
3054 if (decl.ty.zigTypeTag(mod) == .Fn) {
30073055 try func.bin_file.addTableFunction(target_sym_index);
30083056 return WValue{ .function_index = target_sym_index };
30093057 } else if (offset == 0) {
......@@ -3028,142 +3076,201 @@ fn toTwosComplement(value: anytype, bits: u7) std.meta.Int(.unsigned, @typeInfo(
30283076}
30293077
30303078fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
3079 const mod = func.bin_file.base.options.module.?;
30313080 var val = arg_val;
3032 if (val.castTag(.runtime_value)) |rt| {
3033 val = rt.data;
3034 }
3035 if (val.isUndefDeep()) return func.emitUndefined(ty);
3036 if (val.castTag(.decl_ref)) |decl_ref| {
3037 const decl_index = decl_ref.data;
3038 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);
3039 }
3040 if (val.castTag(.decl_ref_mut)) |decl_ref_mut| {
3041 const decl_index = decl_ref_mut.data.decl_index;
3042 return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl_index, 0);
3043 }
3044 const target = func.target;
3045 switch (ty.zigTypeTag()) {
3046 .Void => return WValue{ .none = {} },
3047 .Int => {
3048 const int_info = ty.intInfo(func.target);
3081 switch (mod.intern_pool.indexToKey(val.ip_index)) {
3082 .runtime_value => |rt| val = rt.val.toValue(),
3083 else => {},
3084 }
3085 if (val.isUndefDeep(mod)) return func.emitUndefined(ty);
3086
3087 if (val.ip_index == .none) switch (ty.zigTypeTag(mod)) {
3088 .Array => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
3089 .Struct => {
3090 const struct_obj = mod.typeToStruct(ty).?;
3091 assert(struct_obj.layout == .Packed);
3092 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3093 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3094 const int_val = try mod.intValue(
3095 struct_obj.backing_int_ty,
3096 std.mem.readIntLittle(u64, &buf),
3097 );
3098 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3099 },
3100 .Vector => {
3101 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3102 var buf: [16]u8 = undefined;
3103 val.writeToMemory(ty, mod, &buf) catch unreachable;
3104 return func.storeSimdImmd(buf);
3105 },
3106 .Frame,
3107 .AnyFrame,
3108 => return func.fail("Wasm TODO: LowerConstant for type {}", .{ty.fmt(mod)}),
3109 .Float,
3110 .Union,
3111 .Optional,
3112 .ErrorUnion,
3113 .ErrorSet,
3114 .Int,
3115 .Enum,
3116 .Bool,
3117 .Pointer,
3118 => unreachable, // handled below
3119 .Type,
3120 .Void,
3121 .NoReturn,
3122 .ComptimeFloat,
3123 .ComptimeInt,
3124 .Undefined,
3125 .Null,
3126 .Opaque,
3127 .EnumLiteral,
3128 .Fn,
3129 => unreachable, // comptime-only types
3130 };
3131
3132 switch (mod.intern_pool.indexToKey(val.ip_index)) {
3133 .int_type,
3134 .ptr_type,
3135 .array_type,
3136 .vector_type,
3137 .opt_type,
3138 .anyframe_type,
3139 .error_union_type,
3140 .simple_type,
3141 .struct_type,
3142 .anon_struct_type,
3143 .union_type,
3144 .opaque_type,
3145 .enum_type,
3146 .func_type,
3147 .error_set_type,
3148 .inferred_error_set_type,
3149 => unreachable, // types, not values
3150
3151 .undef, .runtime_value => unreachable, // handled above
3152 .simple_value => |simple_value| switch (simple_value) {
3153 .undefined,
3154 .void,
3155 .null,
3156 .empty_struct,
3157 .@"unreachable",
3158 .generic_poison,
3159 => unreachable, // non-runtime values
3160 .false, .true => return WValue{ .imm32 = switch (simple_value) {
3161 .false => 0,
3162 .true => 1,
3163 else => unreachable,
3164 } },
3165 },
3166 .variable,
3167 .extern_func,
3168 .func,
3169 .enum_literal,
3170 .empty_enum_value,
3171 => unreachable, // non-runtime values
3172 .int => {
3173 const int_info = ty.intInfo(mod);
30493174 switch (int_info.signedness) {
30503175 .signed => switch (int_info.bits) {
30513176 0...32 => return WValue{ .imm32 = @intCast(u32, toTwosComplement(
3052 val.toSignedInt(target),
3177 val.toSignedInt(mod),
30533178 @intCast(u6, int_info.bits),
30543179 )) },
30553180 33...64 => return WValue{ .imm64 = toTwosComplement(
3056 val.toSignedInt(target),
3181 val.toSignedInt(mod),
30573182 @intCast(u7, int_info.bits),
30583183 ) },
30593184 else => unreachable,
30603185 },
30613186 .unsigned => switch (int_info.bits) {
3062 0...32 => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) },
3063 33...64 => return WValue{ .imm64 = val.toUnsignedInt(target) },
3187 0...32 => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(mod)) },
3188 33...64 => return WValue{ .imm64 = val.toUnsignedInt(mod) },
30643189 else => unreachable,
30653190 },
30663191 }
30673192 },
3068 .Bool => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) },
3069 .Float => switch (ty.floatBits(func.target)) {
3070 16 => return WValue{ .imm32 = @bitCast(u16, val.toFloat(f16)) },
3071 32 => return WValue{ .float32 = val.toFloat(f32) },
3072 64 => return WValue{ .float64 = val.toFloat(f64) },
3073 else => unreachable,
3074 },
3075 .Pointer => switch (val.tag()) {
3076 .field_ptr, .elem_ptr, .opt_payload_ptr => return func.lowerParentPtr(val, 0),
3077 .int_u64, .one => return WValue{ .imm32 = @intCast(u32, val.toUnsignedInt(target)) },
3078 .zero, .null_value => return WValue{ .imm32 = 0 },
3079 else => return func.fail("Wasm TODO: lowerConstant for other const pointer tag {}", .{val.tag()}),
3193 .err => |err| {
3194 const int = try mod.getErrorValue(err.name);
3195 return WValue{ .imm32 = int };
30803196 },
3081 .Enum => {
3082 if (val.castTag(.enum_field_index)) |field_index| {
3083 switch (ty.tag()) {
3084 .enum_simple => return WValue{ .imm32 = field_index.data },
3085 .enum_full, .enum_nonexhaustive => {
3086 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
3087 if (enum_full.values.count() != 0) {
3088 const tag_val = enum_full.values.keys()[field_index.data];
3089 return func.lowerConstant(tag_val, enum_full.tag_ty);
3090 } else {
3091 return WValue{ .imm32 = field_index.data };
3092 }
3093 },
3094 .enum_numbered => {
3095 const index = field_index.data;
3096 const enum_data = ty.castTag(.enum_numbered).?.data;
3097 const enum_val = enum_data.values.keys()[index];
3098 return func.lowerConstant(enum_val, enum_data.tag_ty);
3099 },
3100 else => return func.fail("TODO: lowerConstant for enum tag: {}", .{ty.tag()}),
3101 }
3102 } else {
3103 var int_tag_buffer: Type.Payload.Bits = undefined;
3104 const int_tag_ty = ty.intTagType(&int_tag_buffer);
3105 return func.lowerConstant(val, int_tag_ty);
3106 }
3107 },
3108 .ErrorSet => switch (val.tag()) {
3109 .@"error" => {
3110 const kv = try func.bin_file.base.options.module.?.getErrorValue(val.getError().?);
3111 return WValue{ .imm32 = kv.value };
3112 },
3113 else => return WValue{ .imm32 = 0 },
3114 },
3115 .ErrorUnion => {
3116 const error_type = ty.errorUnionSet();
3117 const payload_type = ty.errorUnionPayload();
3118 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
3197 .error_union => |error_union| {
3198 const err_tv: TypedValue = switch (error_union.val) {
3199 .err_name => |err_name| .{
3200 .ty = ty.errorUnionSet(mod),
3201 .val = (try mod.intern(.{ .err = .{
3202 .ty = ty.errorUnionSet(mod).toIntern(),
3203 .name = err_name,
3204 } })).toValue(),
3205 },
3206 .payload => .{
3207 .ty = Type.err_int,
3208 .val = try mod.intValue(Type.err_int, 0),
3209 },
3210 };
3211 const payload_type = ty.errorUnionPayload(mod);
3212 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
31193213 // We use the error type directly as the type.
3120 const is_pl = val.errorUnionIsPayload();
3121 const err_val = if (!is_pl) val else Value.initTag(.zero);
3122 return func.lowerConstant(err_val, error_type);
3214 return func.lowerConstant(err_tv.val, err_tv.ty);
31233215 }
3216
31243217 return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
31253218 },
3126 .Optional => if (ty.optionalReprIsPayload()) {
3127 var buf: Type.Payload.ElemType = undefined;
3128 const pl_ty = ty.optionalChild(&buf);
3129 if (val.castTag(.opt_payload)) |payload| {
3130 return func.lowerConstant(payload.data, pl_ty);
3131 } else if (val.isNull()) {
3132 return WValue{ .imm32 = 0 };
3219 .enum_tag => |enum_tag| {
3220 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
3221 return func.lowerConstant(enum_tag.int.toValue(), int_tag_ty.toType());
3222 },
3223 .float => |float| switch (float.storage) {
3224 .f16 => |f16_val| return WValue{ .imm32 = @bitCast(u16, f16_val) },
3225 .f32 => |f32_val| return WValue{ .float32 = f32_val },
3226 .f64 => |f64_val| return WValue{ .float64 = f64_val },
3227 else => unreachable,
3228 },
3229 .ptr => |ptr| switch (ptr.addr) {
3230 .decl => |decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl, 0),
3231 .mut_decl => |mut_decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, mut_decl.decl, 0),
3232 .int => |int| return func.lowerConstant(int.toValue(), mod.intern_pool.typeOf(int).toType()),
3233 .opt_payload, .elem, .field => return func.lowerParentPtr(val),
3234 else => return func.fail("Wasm TODO: lowerConstant for other const addr tag {}", .{ptr.addr}),
3235 },
3236 .opt => if (ty.optionalReprIsPayload(mod)) {
3237 const pl_ty = ty.optionalChild(mod);
3238 if (val.optionalValue(mod)) |payload| {
3239 return func.lowerConstant(payload, pl_ty);
31333240 } else {
3134 return func.lowerConstant(val, pl_ty);
3241 return WValue{ .imm32 = 0 };
31353242 }
31363243 } else {
3137 const is_pl = val.tag() == .opt_payload;
3138 return WValue{ .imm32 = @boolToInt(is_pl) };
3244 return WValue{ .imm32 = @boolToInt(!val.isNull(mod)) };
31393245 },
3140 .Struct => {
3141 const struct_obj = ty.castTag(.@"struct").?.data;
3142 assert(struct_obj.layout == .Packed);
3143 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3144 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3145 var payload: Value.Payload.U64 = .{
3146 .base = .{ .tag = .int_u64 },
3147 .data = std.mem.readIntLittle(u64, &buf),
3148 };
3149 const int_val = Value.initPayload(&payload.base);
3150 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3151 },
3152 .Vector => {
3153 assert(determineSimdStoreStrategy(ty, target) == .direct);
3154 var buf: [16]u8 = undefined;
3155 val.writeToMemory(ty, func.bin_file.base.options.module.?, &buf) catch unreachable;
3156 return func.storeSimdImmd(buf);
3246 .aggregate => switch (mod.intern_pool.indexToKey(ty.ip_index)) {
3247 .array_type => return func.fail("Wasm TODO: LowerConstant for {}", .{ty.fmt(mod)}),
3248 .vector_type => {
3249 assert(determineSimdStoreStrategy(ty, mod) == .direct);
3250 var buf: [16]u8 = undefined;
3251 val.writeToMemory(ty, mod, &buf) catch unreachable;
3252 return func.storeSimdImmd(buf);
3253 },
3254 .struct_type, .anon_struct_type => {
3255 const struct_obj = mod.typeToStruct(ty).?;
3256 assert(struct_obj.layout == .Packed);
3257 var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer
3258 val.writeToPackedMemory(ty, func.bin_file.base.options.module.?, &buf, 0) catch unreachable;
3259 const int_val = try mod.intValue(
3260 struct_obj.backing_int_ty,
3261 std.mem.readIntLittle(u64, &buf),
3262 );
3263 return func.lowerConstant(int_val, struct_obj.backing_int_ty);
3264 },
3265 else => unreachable,
31573266 },
3158 .Union => {
3267 .un => |union_obj| {
31593268 // in this case we have a packed union which will not be passed by reference.
3160 const union_ty = ty.cast(Type.Payload.Union).?.data;
3161 const union_obj = val.castTag(.@"union").?.data;
3162 const field_index = ty.unionTagFieldIndex(union_obj.tag, func.bin_file.base.options.module.?).?;
3163 const field_ty = union_ty.fields.values()[field_index].ty;
3164 return func.lowerConstant(union_obj.val, field_ty);
3269 const field_index = ty.unionTagFieldIndex(union_obj.tag.toValue(), func.bin_file.base.options.module.?).?;
3270 const field_ty = ty.unionFields(mod).values()[field_index].ty;
3271 return func.lowerConstant(union_obj.val.toValue(), field_ty);
31653272 },
3166 else => |zig_type| return func.fail("Wasm TODO: LowerConstant for zigTypeTag {}", .{zig_type}),
3273 .memoized_call => unreachable,
31673274 }
31683275}
31693276
......@@ -3176,9 +3283,10 @@ fn storeSimdImmd(func: *CodeGen, value: [16]u8) !WValue {
31763283}
31773284
31783285fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
3179 switch (ty.zigTypeTag()) {
3286 const mod = func.bin_file.base.options.module.?;
3287 switch (ty.zigTypeTag(mod)) {
31803288 .Bool, .ErrorSet => return WValue{ .imm32 = 0xaaaaaaaa },
3181 .Int, .Enum => switch (ty.intInfo(func.target).bits) {
3289 .Int, .Enum => switch (ty.intInfo(mod).bits) {
31823290 0...32 => return WValue{ .imm32 = 0xaaaaaaaa },
31833291 33...64 => return WValue{ .imm64 = 0xaaaaaaaaaaaaaaaa },
31843292 else => unreachable,
......@@ -3195,9 +3303,8 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
31953303 else => unreachable,
31963304 },
31973305 .Optional => {
3198 var buf: Type.Payload.ElemType = undefined;
3199 const pl_ty = ty.optionalChild(&buf);
3200 if (ty.optionalReprIsPayload()) {
3306 const pl_ty = ty.optionalChild(mod);
3307 if (ty.optionalReprIsPayload(mod)) {
32013308 return func.emitUndefined(pl_ty);
32023309 }
32033310 return WValue{ .imm32 = 0xaaaaaaaa };
......@@ -3206,11 +3313,11 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
32063313 return WValue{ .imm32 = 0xaaaaaaaa };
32073314 },
32083315 .Struct => {
3209 const struct_obj = ty.castTag(.@"struct").?.data;
3316 const struct_obj = mod.typeToStruct(ty).?;
32103317 assert(struct_obj.layout == .Packed);
32113318 return func.emitUndefined(struct_obj.backing_int_ty);
32123319 },
3213 else => return func.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag()}),
3320 else => return func.fail("Wasm TODO: emitUndefined for type: {}\n", .{ty.zigTypeTag(mod)}),
32143321 }
32153322}
32163323
......@@ -3218,56 +3325,52 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
32183325/// It's illegal to provide a value with a type that cannot be represented
32193326/// as an integer value.
32203327fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
3221 const target = func.target;
3222 switch (ty.zigTypeTag()) {
3223 .Enum => {
3224 if (val.castTag(.enum_field_index)) |field_index| {
3225 switch (ty.tag()) {
3226 .enum_simple => return @bitCast(i32, field_index.data),
3227 .enum_full, .enum_nonexhaustive => {
3228 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
3229 if (enum_full.values.count() != 0) {
3230 const tag_val = enum_full.values.keys()[field_index.data];
3231 return func.valueAsI32(tag_val, enum_full.tag_ty);
3232 } else return @bitCast(i32, field_index.data);
3233 },
3234 .enum_numbered => {
3235 const index = field_index.data;
3236 const enum_data = ty.castTag(.enum_numbered).?.data;
3237 return func.valueAsI32(enum_data.values.keys()[index], enum_data.tag_ty);
3238 },
3239 else => unreachable,
3240 }
3241 } else {
3242 var int_tag_buffer: Type.Payload.Bits = undefined;
3243 const int_tag_ty = ty.intTagType(&int_tag_buffer);
3244 return func.valueAsI32(val, int_tag_ty);
3245 }
3246 },
3247 .Int => switch (ty.intInfo(func.target).signedness) {
3248 .signed => return @truncate(i32, val.toSignedInt(target)),
3249 .unsigned => return @bitCast(i32, @truncate(u32, val.toUnsignedInt(target))),
3250 },
3251 .ErrorSet => {
3252 const kv = func.bin_file.base.options.module.?.getErrorValue(val.getError().?) catch unreachable; // passed invalid `Value` to function
3253 return @bitCast(i32, kv.value);
3328 const mod = func.bin_file.base.options.module.?;
3329
3330 switch (val.ip_index) {
3331 .none => {},
3332 .bool_true => return 1,
3333 .bool_false => return 0,
3334 else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
3335 .enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int, mod),
3336 .int => |int| intStorageAsI32(int.storage, mod),
3337 .ptr => |ptr| intIndexAsI32(&mod.intern_pool, ptr.addr.int, mod),
3338 .err => |err| @bitCast(i32, @intCast(Module.ErrorInt, mod.global_error_set.getIndex(err.name).?)),
3339 else => unreachable,
32543340 },
3255 .Bool => return @intCast(i32, val.toSignedInt(target)),
3256 .Pointer => return @intCast(i32, val.toSignedInt(target)),
3257 else => unreachable, // Programmer called this function for an illegal type
32583341 }
3342
3343 return switch (ty.zigTypeTag(mod)) {
3344 .ErrorSet => @bitCast(i32, val.getErrorInt(mod)),
3345 else => unreachable, // Programmer called this function for an illegal type
3346 };
3347}
3348
3349fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index, mod: *Module) i32 {
3350 return intStorageAsI32(ip.indexToKey(int).int.storage, mod);
3351}
3352
3353fn intStorageAsI32(storage: InternPool.Key.Int.Storage, mod: *Module) i32 {
3354 return switch (storage) {
3355 .i64 => |x| @intCast(i32, x),
3356 .u64 => |x| @bitCast(i32, @intCast(u32, x)),
3357 .big_int => unreachable,
3358 .lazy_align => |ty| @bitCast(i32, ty.toType().abiAlignment(mod)),
3359 .lazy_size => |ty| @bitCast(i32, @intCast(u32, ty.toType().abiSize(mod))),
3360 };
32593361}
32603362
32613363fn airBlock(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3364 const mod = func.bin_file.base.options.module.?;
32623365 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
32633366 const block_ty = func.air.getRefType(ty_pl.ty);
3264 const wasm_block_ty = genBlockType(block_ty, func.target);
3367 const wasm_block_ty = genBlockType(block_ty, mod);
32653368 const extra = func.air.extraData(Air.Block, ty_pl.payload);
32663369 const body = func.air.extra[extra.end..][0..extra.data.body_len];
32673370
32683371 // if wasm_block_ty is non-empty, we create a register to store the temporary value
32693372 const block_result: WValue = if (wasm_block_ty != wasm.block_empty) blk: {
3270 const ty: Type = if (isByRef(block_ty, func.target)) Type.u32 else block_ty;
3373 const ty: Type = if (isByRef(block_ty, mod)) Type.u32 else block_ty;
32713374 break :blk try func.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten
32723375 } else WValue.none;
32733376
......@@ -3369,7 +3472,7 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In
33693472
33703473 const lhs = try func.resolveInst(bin_op.lhs);
33713474 const rhs = try func.resolveInst(bin_op.rhs);
3372 const operand_ty = func.air.typeOf(bin_op.lhs);
3475 const operand_ty = func.typeOf(bin_op.lhs);
33733476 const result = try (try func.cmp(lhs, rhs, operand_ty, op)).toLocal(func, Type.u32); // comparison result is always 32 bits
33743477 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
33753478}
......@@ -3379,16 +3482,16 @@ fn airCmp(func: *CodeGen, inst: Air.Inst.Index, op: std.math.CompareOperator) In
33793482/// NOTE: This leaves the result on top of the stack, rather than a new local.
33803483fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOperator) InnerError!WValue {
33813484 assert(!(lhs != .stack and rhs == .stack));
3382 if (ty.zigTypeTag() == .Optional and !ty.optionalReprIsPayload()) {
3383 var buf: Type.Payload.ElemType = undefined;
3384 const payload_ty = ty.optionalChild(&buf);
3385 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {
3485 const mod = func.bin_file.base.options.module.?;
3486 if (ty.zigTypeTag(mod) == .Optional and !ty.optionalReprIsPayload(mod)) {
3487 const payload_ty = ty.optionalChild(mod);
3488 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
33863489 // When we hit this case, we must check the value of optionals
33873490 // that are not pointers. This means first checking against non-null for
33883491 // both lhs and rhs, as well as checking the payload are matching of lhs and rhs
33893492 return func.cmpOptionals(lhs, rhs, ty, op);
33903493 }
3391 } else if (isByRef(ty, func.target)) {
3494 } else if (isByRef(ty, mod)) {
33923495 return func.cmpBigInt(lhs, rhs, ty, op);
33933496 } else if (ty.isAnyFloat() and ty.floatBits(func.target) == 16) {
33943497 return func.cmpFloat16(lhs, rhs, op);
......@@ -3401,13 +3504,13 @@ fn cmp(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareO
34013504
34023505 const signedness: std.builtin.Signedness = blk: {
34033506 // by default we tell the operand type is unsigned (i.e. bools and enum values)
3404 if (ty.zigTypeTag() != .Int) break :blk .unsigned;
3507 if (ty.zigTypeTag(mod) != .Int) break :blk .unsigned;
34053508
34063509 // incase of an actual integer, we emit the correct signedness
3407 break :blk ty.intInfo(func.target).signedness;
3510 break :blk ty.intInfo(mod).signedness;
34083511 };
34093512 const opcode: wasm.Opcode = buildOpcode(.{
3410 .valtype1 = typeToValtype(ty, func.target),
3513 .valtype1 = typeToValtype(ty, mod),
34113514 .op = switch (op) {
34123515 .lt => .lt,
34133516 .lte => .le,
......@@ -3464,11 +3567,12 @@ fn airCmpLtErrorsLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
34643567}
34653568
34663569fn airBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3570 const mod = func.bin_file.base.options.module.?;
34673571 const br = func.air.instructions.items(.data)[inst].br;
34683572 const block = func.blocks.get(br.block_inst).?;
34693573
34703574 // if operand has codegen bits we should break with a value
3471 if (func.air.typeOf(br.operand).hasRuntimeBitsIgnoreComptime()) {
3575 if (func.typeOf(br.operand).hasRuntimeBitsIgnoreComptime(mod)) {
34723576 const operand = try func.resolveInst(br.operand);
34733577 try func.lowerToStack(operand);
34743578
......@@ -3489,17 +3593,18 @@ fn airNot(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
34893593 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
34903594
34913595 const operand = try func.resolveInst(ty_op.operand);
3492 const operand_ty = func.air.typeOf(ty_op.operand);
3596 const operand_ty = func.typeOf(ty_op.operand);
3597 const mod = func.bin_file.base.options.module.?;
34933598
34943599 const result = result: {
3495 if (operand_ty.zigTypeTag() == .Bool) {
3600 if (operand_ty.zigTypeTag(mod) == .Bool) {
34963601 try func.emitWValue(operand);
34973602 try func.addTag(.i32_eqz);
34983603 const not_tmp = try func.allocLocal(operand_ty);
34993604 try func.addLabel(.local_set, not_tmp.local.value);
35003605 break :result not_tmp;
35013606 } else {
3502 const operand_bits = operand_ty.intInfo(func.target).bits;
3607 const operand_bits = operand_ty.intInfo(mod).bits;
35033608 const wasm_bits = toWasmBits(operand_bits) orelse {
35043609 return func.fail("TODO: Implement binary NOT for integer with bitsize '{d}'", .{operand_bits});
35053610 };
......@@ -3554,8 +3659,8 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
35543659 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
35553660 const result = result: {
35563661 const operand = try func.resolveInst(ty_op.operand);
3557 const wanted_ty = func.air.typeOfIndex(inst);
3558 const given_ty = func.air.typeOf(ty_op.operand);
3662 const wanted_ty = func.typeOfIndex(inst);
3663 const given_ty = func.typeOf(ty_op.operand);
35593664 if (given_ty.isAnyFloat() or wanted_ty.isAnyFloat()) {
35603665 const bitcast_result = try func.bitcast(wanted_ty, given_ty, operand);
35613666 break :result try bitcast_result.toLocal(func, wanted_ty);
......@@ -3566,16 +3671,17 @@ fn airBitcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
35663671}
35673672
35683673fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) InnerError!WValue {
3674 const mod = func.bin_file.base.options.module.?;
35693675 // if we bitcast a float to or from an integer we must use the 'reinterpret' instruction
35703676 if (!(wanted_ty.isAnyFloat() or given_ty.isAnyFloat())) return operand;
3571 if (wanted_ty.tag() == .f16 or given_ty.tag() == .f16) return operand;
3572 if (wanted_ty.bitSize(func.target) > 64) return operand;
3573 assert((wanted_ty.isInt() and given_ty.isAnyFloat()) or (wanted_ty.isAnyFloat() and given_ty.isInt()));
3677 if (wanted_ty.ip_index == .f16_type or given_ty.ip_index == .f16_type) return operand;
3678 if (wanted_ty.bitSize(mod) > 64) return operand;
3679 assert((wanted_ty.isInt(mod) and given_ty.isAnyFloat()) or (wanted_ty.isAnyFloat() and given_ty.isInt(mod)));
35743680
35753681 const opcode = buildOpcode(.{
35763682 .op = .reinterpret,
3577 .valtype1 = typeToValtype(wanted_ty, func.target),
3578 .valtype2 = typeToValtype(given_ty, func.target),
3683 .valtype1 = typeToValtype(wanted_ty, mod),
3684 .valtype2 = typeToValtype(given_ty, mod),
35793685 });
35803686 try func.emitWValue(operand);
35813687 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
......@@ -3583,19 +3689,21 @@ fn bitcast(func: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inn
35833689}
35843690
35853691fn airStructFieldPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3692 const mod = func.bin_file.base.options.module.?;
35863693 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
35873694 const extra = func.air.extraData(Air.StructField, ty_pl.payload);
35883695
35893696 const struct_ptr = try func.resolveInst(extra.data.struct_operand);
3590 const struct_ty = func.air.typeOf(extra.data.struct_operand).childType();
3697 const struct_ty = func.typeOf(extra.data.struct_operand).childType(mod);
35913698 const result = try func.structFieldPtr(inst, extra.data.struct_operand, struct_ptr, struct_ty, extra.data.field_index);
35923699 func.finishAir(inst, result, &.{extra.data.struct_operand});
35933700}
35943701
35953702fn airStructFieldPtrIndex(func: *CodeGen, inst: Air.Inst.Index, index: u32) InnerError!void {
3703 const mod = func.bin_file.base.options.module.?;
35963704 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
35973705 const struct_ptr = try func.resolveInst(ty_op.operand);
3598 const struct_ty = func.air.typeOf(ty_op.operand).childType();
3706 const struct_ty = func.typeOf(ty_op.operand).childType(mod);
35993707
36003708 const result = try func.structFieldPtr(inst, ty_op.operand, struct_ptr, struct_ty, index);
36013709 func.finishAir(inst, result, &.{ty_op.operand});
......@@ -3609,19 +3717,20 @@ fn structFieldPtr(
36093717 struct_ty: Type,
36103718 index: u32,
36113719) InnerError!WValue {
3612 const result_ty = func.air.typeOfIndex(inst);
3613 const offset = switch (struct_ty.containerLayout()) {
3614 .Packed => switch (struct_ty.zigTypeTag()) {
3720 const mod = func.bin_file.base.options.module.?;
3721 const result_ty = func.typeOfIndex(inst);
3722 const offset = switch (struct_ty.containerLayout(mod)) {
3723 .Packed => switch (struct_ty.zigTypeTag(mod)) {
36153724 .Struct => offset: {
3616 if (result_ty.ptrInfo().data.host_size != 0) {
3725 if (result_ty.ptrInfo(mod).host_size != 0) {
36173726 break :offset @as(u32, 0);
36183727 }
3619 break :offset struct_ty.packedStructFieldByteOffset(index, func.target);
3728 break :offset struct_ty.packedStructFieldByteOffset(index, mod);
36203729 },
36213730 .Union => 0,
36223731 else => unreachable,
36233732 },
3624 else => struct_ty.structFieldOffset(index, func.target),
3733 else => struct_ty.structFieldOffset(index, mod),
36253734 };
36263735 // save a load and store when we can simply reuse the operand
36273736 if (offset == 0) {
......@@ -3636,22 +3745,23 @@ fn structFieldPtr(
36363745}
36373746
36383747fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3748 const mod = func.bin_file.base.options.module.?;
36393749 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
36403750 const struct_field = func.air.extraData(Air.StructField, ty_pl.payload).data;
36413751
3642 const struct_ty = func.air.typeOf(struct_field.struct_operand);
3752 const struct_ty = func.typeOf(struct_field.struct_operand);
36433753 const operand = try func.resolveInst(struct_field.struct_operand);
36443754 const field_index = struct_field.field_index;
3645 const field_ty = struct_ty.structFieldType(field_index);
3646 if (!field_ty.hasRuntimeBitsIgnoreComptime()) return func.finishAir(inst, .none, &.{struct_field.struct_operand});
3755 const field_ty = struct_ty.structFieldType(field_index, mod);
3756 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return func.finishAir(inst, .none, &.{struct_field.struct_operand});
36473757
3648 const result = switch (struct_ty.containerLayout()) {
3649 .Packed => switch (struct_ty.zigTypeTag()) {
3758 const result = switch (struct_ty.containerLayout(mod)) {
3759 .Packed => switch (struct_ty.zigTypeTag(mod)) {
36503760 .Struct => result: {
3651 const struct_obj = struct_ty.castTag(.@"struct").?.data;
3652 const offset = struct_obj.packedFieldBitOffset(func.target, field_index);
3761 const struct_obj = mod.typeToStruct(struct_ty).?;
3762 const offset = struct_obj.packedFieldBitOffset(mod, field_index);
36533763 const backing_ty = struct_obj.backing_int_ty;
3654 const wasm_bits = toWasmBits(backing_ty.intInfo(func.target).bits) orelse {
3764 const wasm_bits = toWasmBits(backing_ty.intInfo(mod).bits) orelse {
36553765 return func.fail("TODO: airStructFieldVal for packed structs larger than 128 bits", .{});
36563766 };
36573767 const const_wvalue = if (wasm_bits == 32)
......@@ -3667,25 +3777,17 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
36673777 else
36683778 try func.binOp(operand, const_wvalue, backing_ty, .shr);
36693779
3670 if (field_ty.zigTypeTag() == .Float) {
3671 var payload: Type.Payload.Bits = .{
3672 .base = .{ .tag = .int_unsigned },
3673 .data = @intCast(u16, field_ty.bitSize(func.target)),
3674 };
3675 const int_type = Type.initPayload(&payload.base);
3780 if (field_ty.zigTypeTag(mod) == .Float) {
3781 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
36763782 const truncated = try func.trunc(shifted_value, int_type, backing_ty);
36773783 const bitcasted = try func.bitcast(field_ty, int_type, truncated);
36783784 break :result try bitcasted.toLocal(func, field_ty);
3679 } else if (field_ty.isPtrAtRuntime() and struct_obj.fields.count() == 1) {
3785 } else if (field_ty.isPtrAtRuntime(mod) and struct_obj.fields.count() == 1) {
36803786 // In this case we do not have to perform any transformations,
36813787 // we can simply reuse the operand.
36823788 break :result func.reuseOperand(struct_field.struct_operand, operand);
3683 } else if (field_ty.isPtrAtRuntime()) {
3684 var payload: Type.Payload.Bits = .{
3685 .base = .{ .tag = .int_unsigned },
3686 .data = @intCast(u16, field_ty.bitSize(func.target)),
3687 };
3688 const int_type = Type.initPayload(&payload.base);
3789 } else if (field_ty.isPtrAtRuntime(mod)) {
3790 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
36893791 const truncated = try func.trunc(shifted_value, int_type, backing_ty);
36903792 break :result try truncated.toLocal(func, field_ty);
36913793 }
......@@ -3693,8 +3795,8 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
36933795 break :result try truncated.toLocal(func, field_ty);
36943796 },
36953797 .Union => result: {
3696 if (isByRef(struct_ty, func.target)) {
3697 if (!isByRef(field_ty, func.target)) {
3798 if (isByRef(struct_ty, mod)) {
3799 if (!isByRef(field_ty, mod)) {
36983800 const val = try func.load(operand, field_ty, 0);
36993801 break :result try val.toLocal(func, field_ty);
37003802 } else {
......@@ -3704,26 +3806,14 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37043806 }
37053807 }
37063808
3707 var payload: Type.Payload.Bits = .{
3708 .base = .{ .tag = .int_unsigned },
3709 .data = @intCast(u16, struct_ty.bitSize(func.target)),
3710 };
3711 const union_int_type = Type.initPayload(&payload.base);
3712 if (field_ty.zigTypeTag() == .Float) {
3713 var int_payload: Type.Payload.Bits = .{
3714 .base = .{ .tag = .int_unsigned },
3715 .data = @intCast(u16, field_ty.bitSize(func.target)),
3716 };
3717 const int_type = Type.initPayload(&int_payload.base);
3809 const union_int_type = try mod.intType(.unsigned, @intCast(u16, struct_ty.bitSize(mod)));
3810 if (field_ty.zigTypeTag(mod) == .Float) {
3811 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
37183812 const truncated = try func.trunc(operand, int_type, union_int_type);
37193813 const bitcasted = try func.bitcast(field_ty, int_type, truncated);
37203814 break :result try bitcasted.toLocal(func, field_ty);
3721 } else if (field_ty.isPtrAtRuntime()) {
3722 var int_payload: Type.Payload.Bits = .{
3723 .base = .{ .tag = .int_unsigned },
3724 .data = @intCast(u16, field_ty.bitSize(func.target)),
3725 };
3726 const int_type = Type.initPayload(&int_payload.base);
3815 } else if (field_ty.isPtrAtRuntime(mod)) {
3816 const int_type = try mod.intType(.unsigned, @intCast(u16, field_ty.bitSize(mod)));
37273817 const truncated = try func.trunc(operand, int_type, union_int_type);
37283818 break :result try truncated.toLocal(func, field_ty);
37293819 }
......@@ -3733,11 +3823,10 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37333823 else => unreachable,
37343824 },
37353825 else => result: {
3736 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, func.target)) orelse {
3737 const module = func.bin_file.base.options.module.?;
3738 return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(module)});
3826 const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, mod)) orelse {
3827 return func.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(mod)});
37393828 };
3740 if (isByRef(field_ty, func.target)) {
3829 if (isByRef(field_ty, mod)) {
37413830 switch (operand) {
37423831 .stack_offset => |stack_offset| {
37433832 break :result WValue{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } };
......@@ -3754,11 +3843,12 @@ fn airStructFieldVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37543843}
37553844
37563845fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
3846 const mod = func.bin_file.base.options.module.?;
37573847 // result type is always 'noreturn'
37583848 const blocktype = wasm.block_empty;
37593849 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
37603850 const target = try func.resolveInst(pl_op.operand);
3761 const target_ty = func.air.typeOf(pl_op.operand);
3851 const target_ty = func.typeOf(pl_op.operand);
37623852 const switch_br = func.air.extraData(Air.SwitchBr, pl_op.payload);
37633853 const liveness = try func.liveness.getSwitchBr(func.gpa, inst, switch_br.data.cases_len + 1);
37643854 defer func.gpa.free(liveness.deaths);
......@@ -3787,7 +3877,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
37873877 errdefer func.gpa.free(values);
37883878
37893879 for (items, 0..) |ref, i| {
3790 const item_val = func.air.value(ref).?;
3880 const item_val = (try func.air.value(ref, mod)).?;
37913881 const int_val = func.valueAsI32(item_val, target_ty);
37923882 if (lowest_maybe == null or int_val < lowest_maybe.?) {
37933883 lowest_maybe = int_val;
......@@ -3810,7 +3900,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38103900 // When the target is an integer size larger than u32, we have no way to use the value
38113901 // as an index, therefore we also use an if/else-chain for those cases.
38123902 // TODO: Benchmark this to find a proper value, LLVM seems to draw the line at '40~45'.
3813 const is_sparse = highest - lowest > 50 or target_ty.bitSize(func.target) > 32;
3903 const is_sparse = highest - lowest > 50 or target_ty.bitSize(mod) > 32;
38143904
38153905 const else_body = func.air.extra[extra_index..][0..switch_br.data.else_body_len];
38163906 const has_else_body = else_body.len != 0;
......@@ -3855,7 +3945,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38553945 // for errors that are not present in any branch. This is fine as this default
38563946 // case will never be hit for those cases but we do save runtime cost and size
38573947 // by using a jump table for this instead of if-else chains.
3858 break :blk if (has_else_body or target_ty.zigTypeTag() == .ErrorSet) case_i else unreachable;
3948 break :blk if (has_else_body or target_ty.zigTypeTag(mod) == .ErrorSet) case_i else unreachable;
38593949 };
38603950 func.mir_extra.appendAssumeCapacity(idx);
38613951 } else if (has_else_body) {
......@@ -3866,10 +3956,10 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38663956
38673957 const signedness: std.builtin.Signedness = blk: {
38683958 // by default we tell the operand type is unsigned (i.e. bools and enum values)
3869 if (target_ty.zigTypeTag() != .Int) break :blk .unsigned;
3959 if (target_ty.zigTypeTag(mod) != .Int) break :blk .unsigned;
38703960
38713961 // incase of an actual integer, we emit the correct signedness
3872 break :blk target_ty.intInfo(func.target).signedness;
3962 break :blk target_ty.intInfo(mod).signedness;
38733963 };
38743964
38753965 try func.branches.ensureUnusedCapacity(func.gpa, case_list.items.len + @boolToInt(has_else_body));
......@@ -3882,7 +3972,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38823972 const val = try func.lowerConstant(case.values[0].value, target_ty);
38833973 try func.emitWValue(val);
38843974 const opcode = buildOpcode(.{
3885 .valtype1 = typeToValtype(target_ty, func.target),
3975 .valtype1 = typeToValtype(target_ty, mod),
38863976 .op = .ne, // not equal, because we want to jump out of this block if it does not match the condition.
38873977 .signedness = signedness,
38883978 });
......@@ -3896,7 +3986,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
38963986 const val = try func.lowerConstant(value.value, target_ty);
38973987 try func.emitWValue(val);
38983988 const opcode = buildOpcode(.{
3899 .valtype1 = typeToValtype(target_ty, func.target),
3989 .valtype1 = typeToValtype(target_ty, mod),
39003990 .op = .eq,
39013991 .signedness = signedness,
39023992 });
......@@ -3933,13 +4023,14 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
39334023}
39344024
39354025fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerError!void {
4026 const mod = func.bin_file.base.options.module.?;
39364027 const un_op = func.air.instructions.items(.data)[inst].un_op;
39374028 const operand = try func.resolveInst(un_op);
3938 const err_union_ty = func.air.typeOf(un_op);
3939 const pl_ty = err_union_ty.errorUnionPayload();
4029 const err_union_ty = func.typeOf(un_op);
4030 const pl_ty = err_union_ty.errorUnionPayload(mod);
39404031
39414032 const result = result: {
3942 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
4033 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
39434034 switch (opcode) {
39444035 .i32_ne => break :result WValue{ .imm32 = 0 },
39454036 .i32_eq => break :result WValue{ .imm32 = 1 },
......@@ -3948,10 +4039,10 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
39484039 }
39494040
39504041 try func.emitWValue(operand);
3951 if (pl_ty.hasRuntimeBitsIgnoreComptime()) {
4042 if (pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
39524043 try func.addMemArg(.i32_load16_u, .{
3953 .offset = operand.offset() + @intCast(u32, errUnionErrorOffset(pl_ty, func.target)),
3954 .alignment = Type.anyerror.abiAlignment(func.target),
4044 .offset = operand.offset() + @intCast(u32, errUnionErrorOffset(pl_ty, mod)),
4045 .alignment = Type.anyerror.abiAlignment(mod),
39554046 });
39564047 }
39574048
......@@ -3967,23 +4058,24 @@ fn airIsErr(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode) InnerErro
39674058}
39684059
39694060fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {
4061 const mod = func.bin_file.base.options.module.?;
39704062 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
39714063
39724064 const operand = try func.resolveInst(ty_op.operand);
3973 const op_ty = func.air.typeOf(ty_op.operand);
3974 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
3975 const payload_ty = err_ty.errorUnionPayload();
4065 const op_ty = func.typeOf(ty_op.operand);
4066 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
4067 const payload_ty = err_ty.errorUnionPayload(mod);
39764068
39774069 const result = result: {
3978 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4070 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
39794071 if (op_is_ptr) {
39804072 break :result func.reuseOperand(ty_op.operand, operand);
39814073 }
39824074 break :result WValue{ .none = {} };
39834075 }
39844076
3985 const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, func.target));
3986 if (op_is_ptr or isByRef(payload_ty, func.target)) {
4077 const pl_offset = @intCast(u32, errUnionPayloadOffset(payload_ty, mod));
4078 if (op_is_ptr or isByRef(payload_ty, mod)) {
39874079 break :result try func.buildPointerOffset(operand, pl_offset, .new);
39884080 }
39894081
......@@ -3994,48 +4086,50 @@ fn airUnwrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: boo
39944086}
39954087
39964088fn airUnwrapErrUnionError(func: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void {
4089 const mod = func.bin_file.base.options.module.?;
39974090 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
39984091
39994092 const operand = try func.resolveInst(ty_op.operand);
4000 const op_ty = func.air.typeOf(ty_op.operand);
4001 const err_ty = if (op_is_ptr) op_ty.childType() else op_ty;
4002 const payload_ty = err_ty.errorUnionPayload();
4093 const op_ty = func.typeOf(ty_op.operand);
4094 const err_ty = if (op_is_ptr) op_ty.childType(mod) else op_ty;
4095 const payload_ty = err_ty.errorUnionPayload(mod);
40034096
40044097 const result = result: {
4005 if (err_ty.errorUnionSet().errorSetIsEmpty()) {
4098 if (err_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
40064099 break :result WValue{ .imm32 = 0 };
40074100 }
40084101
4009 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime()) {
4102 if (op_is_ptr or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
40104103 break :result func.reuseOperand(ty_op.operand, operand);
40114104 }
40124105
4013 const error_val = try func.load(operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(payload_ty, func.target)));
4106 const error_val = try func.load(operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(payload_ty, mod)));
40144107 break :result try error_val.toLocal(func, Type.anyerror);
40154108 };
40164109 func.finishAir(inst, result, &.{ty_op.operand});
40174110}
40184111
40194112fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4113 const mod = func.bin_file.base.options.module.?;
40204114 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
40214115
40224116 const operand = try func.resolveInst(ty_op.operand);
4023 const err_ty = func.air.typeOfIndex(inst);
4117 const err_ty = func.typeOfIndex(inst);
40244118
4025 const pl_ty = func.air.typeOf(ty_op.operand);
4119 const pl_ty = func.typeOf(ty_op.operand);
40264120 const result = result: {
4027 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
4121 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
40284122 break :result func.reuseOperand(ty_op.operand, operand);
40294123 }
40304124
40314125 const err_union = try func.allocStack(err_ty);
4032 const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, func.target)), .new);
4126 const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, mod)), .new);
40334127 try func.store(payload_ptr, operand, pl_ty, 0);
40344128
40354129 // ensure we also write '0' to the error part, so any present stack value gets overwritten by it.
40364130 try func.emitWValue(err_union);
40374131 try func.addImm32(0);
4038 const err_val_offset = @intCast(u32, errUnionErrorOffset(pl_ty, func.target));
4132 const err_val_offset = @intCast(u32, errUnionErrorOffset(pl_ty, mod));
40394133 try func.addMemArg(.i32_store16, .{ .offset = err_union.offset() + err_val_offset, .alignment = 2 });
40404134 break :result err_union;
40414135 };
......@@ -4043,24 +4137,25 @@ fn airWrapErrUnionPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void
40434137}
40444138
40454139fn airWrapErrUnionErr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4140 const mod = func.bin_file.base.options.module.?;
40464141 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
40474142
40484143 const operand = try func.resolveInst(ty_op.operand);
40494144 const err_ty = func.air.getRefType(ty_op.ty);
4050 const pl_ty = err_ty.errorUnionPayload();
4145 const pl_ty = err_ty.errorUnionPayload(mod);
40514146
40524147 const result = result: {
4053 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) {
4148 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) {
40544149 break :result func.reuseOperand(ty_op.operand, operand);
40554150 }
40564151
40574152 const err_union = try func.allocStack(err_ty);
40584153 // store error value
4059 try func.store(err_union, operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(pl_ty, func.target)));
4154 try func.store(err_union, operand, Type.anyerror, @intCast(u32, errUnionErrorOffset(pl_ty, mod)));
40604155
40614156 // write 'undefined' to the payload
4062 const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, func.target)), .new);
4063 const len = @intCast(u32, err_ty.errorUnionPayload().abiSize(func.target));
4157 const payload_ptr = try func.buildPointerOffset(err_union, @intCast(u32, errUnionPayloadOffset(pl_ty, mod)), .new);
4158 const len = @intCast(u32, err_ty.errorUnionPayload(mod).abiSize(mod));
40644159 try func.memset(Type.u8, payload_ptr, .{ .imm32 = len }, .{ .imm32 = 0xaa });
40654160
40664161 break :result err_union;
......@@ -4073,16 +4168,17 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
40734168
40744169 const ty = func.air.getRefType(ty_op.ty);
40754170 const operand = try func.resolveInst(ty_op.operand);
4076 const operand_ty = func.air.typeOf(ty_op.operand);
4077 if (ty.zigTypeTag() == .Vector or operand_ty.zigTypeTag() == .Vector) {
4171 const operand_ty = func.typeOf(ty_op.operand);
4172 const mod = func.bin_file.base.options.module.?;
4173 if (ty.zigTypeTag(mod) == .Vector or operand_ty.zigTypeTag(mod) == .Vector) {
40784174 return func.fail("todo Wasm intcast for vectors", .{});
40794175 }
4080 if (ty.abiSize(func.target) > 16 or operand_ty.abiSize(func.target) > 16) {
4176 if (ty.abiSize(mod) > 16 or operand_ty.abiSize(mod) > 16) {
40814177 return func.fail("todo Wasm intcast for bitsize > 128", .{});
40824178 }
40834179
4084 const op_bits = toWasmBits(@intCast(u16, operand_ty.bitSize(func.target))).?;
4085 const wanted_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?;
4180 const op_bits = toWasmBits(@intCast(u16, operand_ty.bitSize(mod))).?;
4181 const wanted_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?;
40864182 const result = if (op_bits == wanted_bits)
40874183 func.reuseOperand(ty_op.operand, operand)
40884184 else
......@@ -4096,8 +4192,9 @@ fn airIntcast(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
40964192/// Asserts type's bitsize <= 128
40974193/// NOTE: May leave the result on the top of the stack.
40984194fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!WValue {
4099 const given_bitsize = @intCast(u16, given.bitSize(func.target));
4100 const wanted_bitsize = @intCast(u16, wanted.bitSize(func.target));
4195 const mod = func.bin_file.base.options.module.?;
4196 const given_bitsize = @intCast(u16, given.bitSize(mod));
4197 const wanted_bitsize = @intCast(u16, wanted.bitSize(mod));
41014198 assert(given_bitsize <= 128);
41024199 assert(wanted_bitsize <= 128);
41034200
......@@ -4110,7 +4207,7 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
41104207 try func.addTag(.i32_wrap_i64);
41114208 } else if (op_bits == 32 and wanted_bits > 32 and wanted_bits <= 64) {
41124209 try func.emitWValue(operand);
4113 try func.addTag(if (wanted.isSignedInt()) .i64_extend_i32_s else .i64_extend_i32_u);
4210 try func.addTag(if (wanted.isSignedInt(mod)) .i64_extend_i32_s else .i64_extend_i32_u);
41144211 } else if (wanted_bits == 128) {
41154212 // for 128bit integers we store the integer in the virtual stack, rather than a local
41164213 const stack_ptr = try func.allocStack(wanted);
......@@ -4119,14 +4216,14 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
41194216 // for 32 bit integers, we first coerce the value into a 64 bit integer before storing it
41204217 // meaning less store operations are required.
41214218 const lhs = if (op_bits == 32) blk: {
4122 break :blk try func.intcast(operand, given, if (wanted.isSignedInt()) Type.i64 else Type.u64);
4219 break :blk try func.intcast(operand, given, if (wanted.isSignedInt(mod)) Type.i64 else Type.u64);
41234220 } else operand;
41244221
41254222 // store msb first
41264223 try func.store(.{ .stack = {} }, lhs, Type.u64, 0 + stack_ptr.offset());
41274224
41284225 // For signed integers we shift msb by 63 (64bit integer - 1 sign bit) and store remaining value
4129 if (wanted.isSignedInt()) {
4226 if (wanted.isSignedInt(mod)) {
41304227 try func.emitWValue(stack_ptr);
41314228 const shr = try func.binOp(lhs, .{ .imm64 = 63 }, Type.i64, .shr);
41324229 try func.store(.{ .stack = {} }, shr, Type.u64, 8 + stack_ptr.offset());
......@@ -4141,11 +4238,12 @@ fn intcast(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
41414238}
41424239
41434240fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind: enum { value, ptr }) InnerError!void {
4241 const mod = func.bin_file.base.options.module.?;
41444242 const un_op = func.air.instructions.items(.data)[inst].un_op;
41454243 const operand = try func.resolveInst(un_op);
41464244
4147 const op_ty = func.air.typeOf(un_op);
4148 const optional_ty = if (op_kind == .ptr) op_ty.childType() else op_ty;
4245 const op_ty = func.typeOf(un_op);
4246 const optional_ty = if (op_kind == .ptr) op_ty.childType(mod) else op_ty;
41494247 const is_null = try func.isNull(operand, optional_ty, opcode);
41504248 const result = try is_null.toLocal(func, optional_ty);
41514249 func.finishAir(inst, result, &.{un_op});
......@@ -4154,20 +4252,19 @@ fn airIsNull(func: *CodeGen, inst: Air.Inst.Index, opcode: wasm.Opcode, op_kind:
41544252/// For a given type and operand, checks if it's considered `null`.
41554253/// NOTE: Leaves the result on the stack
41564254fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcode) InnerError!WValue {
4255 const mod = func.bin_file.base.options.module.?;
41574256 try func.emitWValue(operand);
4158 var buf: Type.Payload.ElemType = undefined;
4159 const payload_ty = optional_ty.optionalChild(&buf);
4160 if (!optional_ty.optionalReprIsPayload()) {
4257 const payload_ty = optional_ty.optionalChild(mod);
4258 if (!optional_ty.optionalReprIsPayload(mod)) {
41614259 // When payload is zero-bits, we can treat operand as a value, rather than
41624260 // a pointer to the stack value
4163 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {
4164 const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse {
4165 const module = func.bin_file.base.options.module.?;
4166 return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(module)});
4261 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4262 const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse {
4263 return func.fail("Optional type {} too big to fit into stack frame", .{optional_ty.fmt(mod)});
41674264 };
41684265 try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 });
41694266 }
4170 } else if (payload_ty.isSlice()) {
4267 } else if (payload_ty.isSlice(mod)) {
41714268 switch (func.arch()) {
41724269 .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }),
41734270 .wasm64 => try func.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }),
......@@ -4183,18 +4280,19 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod
41834280}
41844281
41854282fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4283 const mod = func.bin_file.base.options.module.?;
41864284 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
4187 const opt_ty = func.air.typeOf(ty_op.operand);
4188 const payload_ty = func.air.typeOfIndex(inst);
4189 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4285 const opt_ty = func.typeOf(ty_op.operand);
4286 const payload_ty = func.typeOfIndex(inst);
4287 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
41904288 return func.finishAir(inst, .none, &.{ty_op.operand});
41914289 }
41924290
41934291 const result = result: {
41944292 const operand = try func.resolveInst(ty_op.operand);
4195 if (opt_ty.optionalReprIsPayload()) break :result func.reuseOperand(ty_op.operand, operand);
4293 if (opt_ty.optionalReprIsPayload(mod)) break :result func.reuseOperand(ty_op.operand, operand);
41964294
4197 if (isByRef(payload_ty, func.target)) {
4295 if (isByRef(payload_ty, mod)) {
41984296 break :result try func.buildPointerOffset(operand, 0, .new);
41994297 }
42004298
......@@ -4205,14 +4303,14 @@ fn airOptionalPayload(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42054303}
42064304
42074305fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4306 const mod = func.bin_file.base.options.module.?;
42084307 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
42094308 const operand = try func.resolveInst(ty_op.operand);
4210 const opt_ty = func.air.typeOf(ty_op.operand).childType();
4309 const opt_ty = func.typeOf(ty_op.operand).childType(mod);
42114310
42124311 const result = result: {
4213 var buf: Type.Payload.ElemType = undefined;
4214 const payload_ty = opt_ty.optionalChild(&buf);
4215 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or opt_ty.optionalReprIsPayload()) {
4312 const payload_ty = opt_ty.optionalChild(mod);
4313 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or opt_ty.optionalReprIsPayload(mod)) {
42164314 break :result func.reuseOperand(ty_op.operand, operand);
42174315 }
42184316
......@@ -4222,22 +4320,21 @@ fn airOptionalPayloadPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42224320}
42234321
42244322fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4323 const mod = func.bin_file.base.options.module.?;
42254324 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
42264325 const operand = try func.resolveInst(ty_op.operand);
4227 const opt_ty = func.air.typeOf(ty_op.operand).childType();
4228 var buf: Type.Payload.ElemType = undefined;
4229 const payload_ty = opt_ty.optionalChild(&buf);
4230 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4326 const opt_ty = func.typeOf(ty_op.operand).childType(mod);
4327 const payload_ty = opt_ty.optionalChild(mod);
4328 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
42314329 return func.fail("TODO: Implement OptionalPayloadPtrSet for optional with zero-sized type {}", .{payload_ty.fmtDebug()});
42324330 }
42334331
4234 if (opt_ty.optionalReprIsPayload()) {
4332 if (opt_ty.optionalReprIsPayload(mod)) {
42354333 return func.finishAir(inst, operand, &.{ty_op.operand});
42364334 }
42374335
4238 const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse {
4239 const module = func.bin_file.base.options.module.?;
4240 return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(module)});
4336 const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse {
4337 return func.fail("Optional type {} too big to fit into stack frame", .{opt_ty.fmt(mod)});
42414338 };
42424339
42434340 try func.emitWValue(operand);
......@@ -4250,11 +4347,12 @@ fn airOptionalPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
42504347
42514348fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42524349 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
4253 const payload_ty = func.air.typeOf(ty_op.operand);
4350 const payload_ty = func.typeOf(ty_op.operand);
4351 const mod = func.bin_file.base.options.module.?;
42544352
42554353 const result = result: {
4256 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4257 const non_null_bit = try func.allocStack(Type.initTag(.u1));
4354 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4355 const non_null_bit = try func.allocStack(Type.u1);
42584356 try func.emitWValue(non_null_bit);
42594357 try func.addImm32(1);
42604358 try func.addMemArg(.i32_store8, .{ .offset = non_null_bit.offset(), .alignment = 1 });
......@@ -4262,13 +4360,12 @@ fn airWrapOptional(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42624360 }
42634361
42644362 const operand = try func.resolveInst(ty_op.operand);
4265 const op_ty = func.air.typeOfIndex(inst);
4266 if (op_ty.optionalReprIsPayload()) {
4363 const op_ty = func.typeOfIndex(inst);
4364 if (op_ty.optionalReprIsPayload(mod)) {
42674365 break :result func.reuseOperand(ty_op.operand, operand);
42684366 }
4269 const offset = std.math.cast(u32, payload_ty.abiSize(func.target)) orelse {
4270 const module = func.bin_file.base.options.module.?;
4271 return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(module)});
4367 const offset = std.math.cast(u32, payload_ty.abiSize(mod)) orelse {
4368 return func.fail("Optional type {} too big to fit into stack frame", .{op_ty.fmt(mod)});
42724369 };
42734370
42744371 // Create optional type, set the non-null bit, and store the operand inside the optional type
......@@ -4291,7 +4388,7 @@ fn airSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
42914388
42924389 const lhs = try func.resolveInst(bin_op.lhs);
42934390 const rhs = try func.resolveInst(bin_op.rhs);
4294 const slice_ty = func.air.typeOfIndex(inst);
4391 const slice_ty = func.typeOfIndex(inst);
42954392
42964393 const slice = try func.allocStack(slice_ty);
42974394 try func.store(slice, lhs, Type.usize, 0);
......@@ -4308,13 +4405,14 @@ fn airSliceLen(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43084405}
43094406
43104407fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4408 const mod = func.bin_file.base.options.module.?;
43114409 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
43124410
4313 const slice_ty = func.air.typeOf(bin_op.lhs);
4411 const slice_ty = func.typeOf(bin_op.lhs);
43144412 const slice = try func.resolveInst(bin_op.lhs);
43154413 const index = try func.resolveInst(bin_op.rhs);
4316 const elem_ty = slice_ty.childType();
4317 const elem_size = elem_ty.abiSize(func.target);
4414 const elem_ty = slice_ty.childType(mod);
4415 const elem_size = elem_ty.abiSize(mod);
43184416
43194417 // load pointer onto stack
43204418 _ = try func.load(slice, Type.usize, 0);
......@@ -4328,7 +4426,7 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43284426 const result_ptr = try func.allocLocal(Type.usize);
43294427 try func.addLabel(.local_set, result_ptr.local.value);
43304428
4331 const result = if (!isByRef(elem_ty, func.target)) result: {
4429 const result = if (!isByRef(elem_ty, mod)) result: {
43324430 const elem_val = try func.load(result_ptr, elem_ty, 0);
43334431 break :result try elem_val.toLocal(func, elem_ty);
43344432 } else result_ptr;
......@@ -4337,11 +4435,12 @@ fn airSliceElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43374435}
43384436
43394437fn airSliceElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4438 const mod = func.bin_file.base.options.module.?;
43404439 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
43414440 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
43424441
4343 const elem_ty = func.air.getRefType(ty_pl.ty).childType();
4344 const elem_size = elem_ty.abiSize(func.target);
4442 const elem_ty = func.air.getRefType(ty_pl.ty).childType(mod);
4443 const elem_size = elem_ty.abiSize(mod);
43454444
43464445 const slice = try func.resolveInst(bin_op.lhs);
43474446 const index = try func.resolveInst(bin_op.rhs);
......@@ -4380,7 +4479,7 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43804479
43814480 const operand = try func.resolveInst(ty_op.operand);
43824481 const wanted_ty = func.air.getRefType(ty_op.ty);
4383 const op_ty = func.air.typeOf(ty_op.operand);
4482 const op_ty = func.typeOf(ty_op.operand);
43844483
43854484 const result = try func.trunc(operand, wanted_ty, op_ty);
43864485 func.finishAir(inst, try result.toLocal(func, wanted_ty), &.{ty_op.operand});
......@@ -4389,13 +4488,14 @@ fn airTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
43894488/// Truncates a given operand to a given type, discarding any overflown bits.
43904489/// NOTE: Resulting value is left on the stack.
43914490fn trunc(func: *CodeGen, operand: WValue, wanted_ty: Type, given_ty: Type) InnerError!WValue {
4392 const given_bits = @intCast(u16, given_ty.bitSize(func.target));
4491 const mod = func.bin_file.base.options.module.?;
4492 const given_bits = @intCast(u16, given_ty.bitSize(mod));
43934493 if (toWasmBits(given_bits) == null) {
43944494 return func.fail("TODO: Implement wasm integer truncation for integer bitsize: {d}", .{given_bits});
43954495 }
43964496
43974497 var result = try func.intcast(operand, given_ty, wanted_ty);
4398 const wanted_bits = @intCast(u16, wanted_ty.bitSize(func.target));
4498 const wanted_bits = @intCast(u16, wanted_ty.bitSize(mod));
43994499 const wasm_bits = toWasmBits(wanted_bits).?;
44004500 if (wasm_bits != wanted_bits) {
44014501 result = try func.wrapOperand(result, wanted_ty);
......@@ -4412,32 +4512,34 @@ fn airBoolToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
44124512}
44134513
44144514fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4515 const mod = func.bin_file.base.options.module.?;
44154516 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
44164517
44174518 const operand = try func.resolveInst(ty_op.operand);
4418 const array_ty = func.air.typeOf(ty_op.operand).childType();
4519 const array_ty = func.typeOf(ty_op.operand).childType(mod);
44194520 const slice_ty = func.air.getRefType(ty_op.ty);
44204521
44214522 // create a slice on the stack
44224523 const slice_local = try func.allocStack(slice_ty);
44234524
44244525 // store the array ptr in the slice
4425 if (array_ty.hasRuntimeBitsIgnoreComptime()) {
4526 if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
44264527 try func.store(slice_local, operand, Type.usize, 0);
44274528 }
44284529
44294530 // store the length of the array in the slice
4430 const len = WValue{ .imm32 = @intCast(u32, array_ty.arrayLen()) };
4531 const len = WValue{ .imm32 = @intCast(u32, array_ty.arrayLen(mod)) };
44314532 try func.store(slice_local, len, Type.usize, func.ptrSize());
44324533
44334534 func.finishAir(inst, slice_local, &.{ty_op.operand});
44344535}
44354536
44364537fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4538 const mod = func.bin_file.base.options.module.?;
44374539 const un_op = func.air.instructions.items(.data)[inst].un_op;
44384540 const operand = try func.resolveInst(un_op);
4439 const ptr_ty = func.air.typeOf(un_op);
4440 const result = if (ptr_ty.isSlice())
4541 const ptr_ty = func.typeOf(un_op);
4542 const result = if (ptr_ty.isSlice(mod))
44414543 try func.slicePtr(operand)
44424544 else switch (operand) {
44434545 // for stack offset, return a pointer to this offset.
......@@ -4448,16 +4550,17 @@ fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
44484550}
44494551
44504552fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4553 const mod = func.bin_file.base.options.module.?;
44514554 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
44524555
4453 const ptr_ty = func.air.typeOf(bin_op.lhs);
4556 const ptr_ty = func.typeOf(bin_op.lhs);
44544557 const ptr = try func.resolveInst(bin_op.lhs);
44554558 const index = try func.resolveInst(bin_op.rhs);
4456 const elem_ty = ptr_ty.childType();
4457 const elem_size = elem_ty.abiSize(func.target);
4559 const elem_ty = ptr_ty.childType(mod);
4560 const elem_size = elem_ty.abiSize(mod);
44584561
44594562 // load pointer onto the stack
4460 if (ptr_ty.isSlice()) {
4563 if (ptr_ty.isSlice(mod)) {
44614564 _ = try func.load(ptr, Type.usize, 0);
44624565 } else {
44634566 try func.lowerToStack(ptr);
......@@ -4472,7 +4575,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
44724575 const elem_result = val: {
44734576 var result = try func.allocLocal(Type.usize);
44744577 try func.addLabel(.local_set, result.local.value);
4475 if (isByRef(elem_ty, func.target)) {
4578 if (isByRef(elem_ty, mod)) {
44764579 break :val result;
44774580 }
44784581 defer result.free(func); // only free if it's not returned like above
......@@ -4484,18 +4587,19 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
44844587}
44854588
44864589fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4590 const mod = func.bin_file.base.options.module.?;
44874591 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
44884592 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
44894593
4490 const ptr_ty = func.air.typeOf(bin_op.lhs);
4491 const elem_ty = func.air.getRefType(ty_pl.ty).childType();
4492 const elem_size = elem_ty.abiSize(func.target);
4594 const ptr_ty = func.typeOf(bin_op.lhs);
4595 const elem_ty = func.air.getRefType(ty_pl.ty).childType(mod);
4596 const elem_size = elem_ty.abiSize(mod);
44934597
44944598 const ptr = try func.resolveInst(bin_op.lhs);
44954599 const index = try func.resolveInst(bin_op.rhs);
44964600
44974601 // load pointer onto the stack
4498 if (ptr_ty.isSlice()) {
4602 if (ptr_ty.isSlice(mod)) {
44994603 _ = try func.load(ptr, Type.usize, 0);
45004604 } else {
45014605 try func.lowerToStack(ptr);
......@@ -4513,24 +4617,25 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
45134617}
45144618
45154619fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
4620 const mod = func.bin_file.base.options.module.?;
45164621 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
45174622 const bin_op = func.air.extraData(Air.Bin, ty_pl.payload).data;
45184623
45194624 const ptr = try func.resolveInst(bin_op.lhs);
45204625 const offset = try func.resolveInst(bin_op.rhs);
4521 const ptr_ty = func.air.typeOf(bin_op.lhs);
4522 const pointee_ty = switch (ptr_ty.ptrSize()) {
4523 .One => ptr_ty.childType().childType(), // ptr to array, so get array element type
4524 else => ptr_ty.childType(),
4626 const ptr_ty = func.typeOf(bin_op.lhs);
4627 const pointee_ty = switch (ptr_ty.ptrSize(mod)) {
4628 .One => ptr_ty.childType(mod).childType(mod), // ptr to array, so get array element type
4629 else => ptr_ty.childType(mod),
45254630 };
45264631
4527 const valtype = typeToValtype(Type.usize, func.target);
4632 const valtype = typeToValtype(Type.usize, mod);
45284633 const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul });
45294634 const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op });
45304635
45314636 try func.lowerToStack(ptr);
45324637 try func.emitWValue(offset);
4533 try func.addImm32(@bitCast(i32, @intCast(u32, pointee_ty.abiSize(func.target))));
4638 try func.addImm32(@bitCast(i32, @intCast(u32, pointee_ty.abiSize(mod))));
45344639 try func.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode));
45354640 try func.addTag(Mir.Inst.Tag.fromOpcode(bin_opcode));
45364641
......@@ -4540,6 +4645,7 @@ fn airPtrBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
45404645}
45414646
45424647fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void {
4648 const mod = func.bin_file.base.options.module.?;
45434649 if (safety) {
45444650 // TODO if the value is undef, write 0xaa bytes to dest
45454651 } else {
......@@ -4548,18 +4654,18 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
45484654 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
45494655
45504656 const ptr = try func.resolveInst(bin_op.lhs);
4551 const ptr_ty = func.air.typeOf(bin_op.lhs);
4657 const ptr_ty = func.typeOf(bin_op.lhs);
45524658 const value = try func.resolveInst(bin_op.rhs);
4553 const len = switch (ptr_ty.ptrSize()) {
4659 const len = switch (ptr_ty.ptrSize(mod)) {
45544660 .Slice => try func.sliceLen(ptr),
4555 .One => @as(WValue, .{ .imm32 = @intCast(u32, ptr_ty.childType().arrayLen()) }),
4661 .One => @as(WValue, .{ .imm32 = @intCast(u32, ptr_ty.childType(mod).arrayLen(mod)) }),
45564662 .C, .Many => unreachable,
45574663 };
45584664
4559 const elem_ty = if (ptr_ty.ptrSize() == .One)
4560 ptr_ty.childType().childType()
4665 const elem_ty = if (ptr_ty.ptrSize(mod) == .One)
4666 ptr_ty.childType(mod).childType(mod)
45614667 else
4562 ptr_ty.childType();
4668 ptr_ty.childType(mod);
45634669
45644670 const dst_ptr = try func.sliceOrArrayPtr(ptr, ptr_ty);
45654671 try func.memset(elem_ty, dst_ptr, len, value);
......@@ -4572,7 +4678,8 @@ fn airMemset(func: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void
45724678/// this to wasm's memset instruction. When the feature is not present,
45734679/// we implement it manually.
45744680fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue) InnerError!void {
4575 const abi_size = @intCast(u32, elem_ty.abiSize(func.target));
4681 const mod = func.bin_file.base.options.module.?;
4682 const abi_size = @intCast(u32, elem_ty.abiSize(mod));
45764683
45774684 // When bulk_memory is enabled, we lower it to wasm's memset instruction.
45784685 // If not, we lower it ourselves.
......@@ -4660,30 +4767,31 @@ fn memset(func: *CodeGen, elem_ty: Type, ptr: WValue, len: WValue, value: WValue
46604767}
46614768
46624769fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4770 const mod = func.bin_file.base.options.module.?;
46634771 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
46644772
4665 const array_ty = func.air.typeOf(bin_op.lhs);
4773 const array_ty = func.typeOf(bin_op.lhs);
46664774 const array = try func.resolveInst(bin_op.lhs);
46674775 const index = try func.resolveInst(bin_op.rhs);
4668 const elem_ty = array_ty.childType();
4669 const elem_size = elem_ty.abiSize(func.target);
4776 const elem_ty = array_ty.childType(mod);
4777 const elem_size = elem_ty.abiSize(mod);
46704778
4671 if (isByRef(array_ty, func.target)) {
4779 if (isByRef(array_ty, mod)) {
46724780 try func.lowerToStack(array);
46734781 try func.emitWValue(index);
46744782 try func.addImm32(@bitCast(i32, @intCast(u32, elem_size)));
46754783 try func.addTag(.i32_mul);
46764784 try func.addTag(.i32_add);
46774785 } else {
4678 std.debug.assert(array_ty.zigTypeTag() == .Vector);
4786 std.debug.assert(array_ty.zigTypeTag(mod) == .Vector);
46794787
46804788 switch (index) {
46814789 inline .imm32, .imm64 => |lane| {
4682 const opcode: wasm.SimdOpcode = switch (elem_ty.bitSize(func.target)) {
4683 8 => if (elem_ty.isSignedInt()) .i8x16_extract_lane_s else .i8x16_extract_lane_u,
4684 16 => if (elem_ty.isSignedInt()) .i16x8_extract_lane_s else .i16x8_extract_lane_u,
4685 32 => if (elem_ty.isInt()) .i32x4_extract_lane else .f32x4_extract_lane,
4686 64 => if (elem_ty.isInt()) .i64x2_extract_lane else .f64x2_extract_lane,
4790 const opcode: wasm.SimdOpcode = switch (elem_ty.bitSize(mod)) {
4791 8 => if (elem_ty.isSignedInt(mod)) .i8x16_extract_lane_s else .i8x16_extract_lane_u,
4792 16 => if (elem_ty.isSignedInt(mod)) .i16x8_extract_lane_s else .i16x8_extract_lane_u,
4793 32 => if (elem_ty.isInt(mod)) .i32x4_extract_lane else .f32x4_extract_lane,
4794 64 => if (elem_ty.isInt(mod)) .i64x2_extract_lane else .f64x2_extract_lane,
46874795 else => unreachable,
46884796 };
46894797
......@@ -4715,7 +4823,7 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47154823 var result = try func.allocLocal(Type.usize);
47164824 try func.addLabel(.local_set, result.local.value);
47174825
4718 if (isByRef(elem_ty, func.target)) {
4826 if (isByRef(elem_ty, mod)) {
47194827 break :val result;
47204828 }
47214829 defer result.free(func); // only free if no longer needed and not returned like above
......@@ -4728,22 +4836,23 @@ fn airArrayElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47284836}
47294837
47304838fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4839 const mod = func.bin_file.base.options.module.?;
47314840 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
47324841
47334842 const operand = try func.resolveInst(ty_op.operand);
4734 const dest_ty = func.air.typeOfIndex(inst);
4735 const op_ty = func.air.typeOf(ty_op.operand);
4843 const dest_ty = func.typeOfIndex(inst);
4844 const op_ty = func.typeOf(ty_op.operand);
47364845
4737 if (op_ty.abiSize(func.target) > 8) {
4846 if (op_ty.abiSize(mod) > 8) {
47384847 return func.fail("TODO: floatToInt for integers/floats with bitsize larger than 64 bits", .{});
47394848 }
47404849
47414850 try func.emitWValue(operand);
47424851 const op = buildOpcode(.{
47434852 .op = .trunc,
4744 .valtype1 = typeToValtype(dest_ty, func.target),
4745 .valtype2 = typeToValtype(op_ty, func.target),
4746 .signedness = if (dest_ty.isSignedInt()) .signed else .unsigned,
4853 .valtype1 = typeToValtype(dest_ty, mod),
4854 .valtype2 = typeToValtype(op_ty, mod),
4855 .signedness = if (dest_ty.isSignedInt(mod)) .signed else .unsigned,
47474856 });
47484857 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
47494858 const wrapped = try func.wrapOperand(.{ .stack = {} }, dest_ty);
......@@ -4752,22 +4861,23 @@ fn airFloatToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47524861}
47534862
47544863fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4864 const mod = func.bin_file.base.options.module.?;
47554865 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
47564866
47574867 const operand = try func.resolveInst(ty_op.operand);
4758 const dest_ty = func.air.typeOfIndex(inst);
4759 const op_ty = func.air.typeOf(ty_op.operand);
4868 const dest_ty = func.typeOfIndex(inst);
4869 const op_ty = func.typeOf(ty_op.operand);
47604870
4761 if (op_ty.abiSize(func.target) > 8) {
4871 if (op_ty.abiSize(mod) > 8) {
47624872 return func.fail("TODO: intToFloat for integers/floats with bitsize larger than 64 bits", .{});
47634873 }
47644874
47654875 try func.emitWValue(operand);
47664876 const op = buildOpcode(.{
47674877 .op = .convert,
4768 .valtype1 = typeToValtype(dest_ty, func.target),
4769 .valtype2 = typeToValtype(op_ty, func.target),
4770 .signedness = if (op_ty.isSignedInt()) .signed else .unsigned,
4878 .valtype1 = typeToValtype(dest_ty, mod),
4879 .valtype2 = typeToValtype(op_ty, mod),
4880 .signedness = if (op_ty.isSignedInt(mod)) .signed else .unsigned,
47714881 });
47724882 try func.addTag(Mir.Inst.Tag.fromOpcode(op));
47734883
......@@ -4777,18 +4887,19 @@ fn airIntToFloat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
47774887}
47784888
47794889fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4890 const mod = func.bin_file.base.options.module.?;
47804891 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
47814892 const operand = try func.resolveInst(ty_op.operand);
4782 const ty = func.air.typeOfIndex(inst);
4783 const elem_ty = ty.childType();
4893 const ty = func.typeOfIndex(inst);
4894 const elem_ty = ty.childType(mod);
47844895
4785 if (determineSimdStoreStrategy(ty, func.target) == .direct) blk: {
4896 if (determineSimdStoreStrategy(ty, mod) == .direct) blk: {
47864897 switch (operand) {
47874898 // when the operand lives in the linear memory section, we can directly
47884899 // load and splat the value at once. Meaning we do not first have to load
47894900 // the scalar value onto the stack.
47904901 .stack_offset, .memory, .memory_offset => {
4791 const opcode = switch (elem_ty.bitSize(func.target)) {
4902 const opcode = switch (elem_ty.bitSize(mod)) {
47924903 8 => std.wasm.simdOpcode(.v128_load8_splat),
47934904 16 => std.wasm.simdOpcode(.v128_load16_splat),
47944905 32 => std.wasm.simdOpcode(.v128_load32_splat),
......@@ -4803,18 +4914,18 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48034914 try func.mir_extra.appendSlice(func.gpa, &[_]u32{
48044915 opcode,
48054916 operand.offset(),
4806 elem_ty.abiAlignment(func.target),
4917 elem_ty.abiAlignment(mod),
48074918 });
48084919 try func.addInst(.{ .tag = .simd_prefix, .data = .{ .payload = extra_index } });
48094920 try func.addLabel(.local_set, result.local.value);
48104921 return func.finishAir(inst, result, &.{ty_op.operand});
48114922 },
48124923 .local => {
4813 const opcode = switch (elem_ty.bitSize(func.target)) {
4924 const opcode = switch (elem_ty.bitSize(mod)) {
48144925 8 => std.wasm.simdOpcode(.i8x16_splat),
48154926 16 => std.wasm.simdOpcode(.i16x8_splat),
4816 32 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i32x4_splat) else std.wasm.simdOpcode(.f32x4_splat),
4817 64 => if (elem_ty.isInt()) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat),
4927 32 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i32x4_splat) else std.wasm.simdOpcode(.f32x4_splat),
4928 64 => if (elem_ty.isInt(mod)) std.wasm.simdOpcode(.i64x2_splat) else std.wasm.simdOpcode(.f64x2_splat),
48184929 else => break :blk, // Cannot make use of simd-instructions
48194930 };
48204931 const result = try func.allocLocal(ty);
......@@ -4828,14 +4939,14 @@ fn airSplat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48284939 else => unreachable,
48294940 }
48304941 }
4831 const elem_size = elem_ty.bitSize(func.target);
4832 const vector_len = @intCast(usize, ty.vectorLen());
4942 const elem_size = elem_ty.bitSize(mod);
4943 const vector_len = @intCast(usize, ty.vectorLen(mod));
48334944 if ((!std.math.isPowerOfTwo(elem_size) or elem_size % 8 != 0) and vector_len > 1) {
48344945 return func.fail("TODO: WebAssembly `@splat` for arbitrary element bitsize {d}", .{elem_size});
48354946 }
48364947
48374948 const result = try func.allocStack(ty);
4838 const elem_byte_size = @intCast(u32, elem_ty.abiSize(func.target));
4949 const elem_byte_size = @intCast(u32, elem_ty.abiSize(mod));
48394950 var index: usize = 0;
48404951 var offset: u32 = 0;
48414952 while (index < vector_len) : (index += 1) {
......@@ -4855,26 +4966,25 @@ fn airSelect(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48554966}
48564967
48574968fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
4858 const inst_ty = func.air.typeOfIndex(inst);
4969 const mod = func.bin_file.base.options.module.?;
4970 const inst_ty = func.typeOfIndex(inst);
48594971 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
48604972 const extra = func.air.extraData(Air.Shuffle, ty_pl.payload).data;
48614973
48624974 const a = try func.resolveInst(extra.a);
48634975 const b = try func.resolveInst(extra.b);
4864 const mask = func.air.values[extra.mask];
4976 const mask = extra.mask.toValue();
48654977 const mask_len = extra.mask_len;
48664978
4867 const child_ty = inst_ty.childType();
4868 const elem_size = child_ty.abiSize(func.target);
4979 const child_ty = inst_ty.childType(mod);
4980 const elem_size = child_ty.abiSize(mod);
48694981
4870 const module = func.bin_file.base.options.module.?;
48714982 // TODO: One of them could be by ref; handle in loop
4872 if (isByRef(func.air.typeOf(extra.a), func.target) or isByRef(inst_ty, func.target)) {
4983 if (isByRef(func.typeOf(extra.a), mod) or isByRef(inst_ty, mod)) {
48734984 const result = try func.allocStack(inst_ty);
48744985
48754986 for (0..mask_len) |index| {
4876 var buf: Value.ElemValueBuffer = undefined;
4877 const value = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target);
4987 const value = (try mask.elemValue(mod, index)).toSignedInt(mod);
48784988
48794989 try func.emitWValue(result);
48804990
......@@ -4894,8 +5004,7 @@ fn airShuffle(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
48945004
48955005 var lanes = std.mem.asBytes(operands[1..]);
48965006 for (0..@intCast(usize, mask_len)) |index| {
4897 var buf: Value.ElemValueBuffer = undefined;
4898 const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(func.target);
5007 const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod);
48995008 const base_index = if (mask_elem >= 0)
49005009 @intCast(u8, @intCast(i64, elem_size) * mask_elem)
49015010 else
......@@ -4926,25 +5035,26 @@ fn airReduce(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
49265035}
49275036
49285037fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5038 const mod = func.bin_file.base.options.module.?;
49295039 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
4930 const result_ty = func.air.typeOfIndex(inst);
4931 const len = @intCast(usize, result_ty.arrayLen());
5040 const result_ty = func.typeOfIndex(inst);
5041 const len = @intCast(usize, result_ty.arrayLen(mod));
49325042 const elements = @ptrCast([]const Air.Inst.Ref, func.air.extra[ty_pl.payload..][0..len]);
49335043
49345044 const result: WValue = result_value: {
4935 switch (result_ty.zigTypeTag()) {
5045 switch (result_ty.zigTypeTag(mod)) {
49365046 .Array => {
49375047 const result = try func.allocStack(result_ty);
4938 const elem_ty = result_ty.childType();
4939 const elem_size = @intCast(u32, elem_ty.abiSize(func.target));
4940 const sentinel = if (result_ty.sentinel()) |sent| blk: {
5048 const elem_ty = result_ty.childType(mod);
5049 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
5050 const sentinel = if (result_ty.sentinel(mod)) |sent| blk: {
49415051 break :blk try func.lowerConstant(sent, elem_ty);
49425052 } else null;
49435053
49445054 // When the element type is by reference, we must copy the entire
49455055 // value. It is therefore safer to move the offset pointer and store
49465056 // each value individually, instead of using store offsets.
4947 if (isByRef(elem_ty, func.target)) {
5057 if (isByRef(elem_ty, mod)) {
49485058 // copy stack pointer into a temporary local, which is
49495059 // moved for each element to store each value in the right position.
49505060 const offset = try func.buildPointerOffset(result, 0, .new);
......@@ -4972,18 +5082,18 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
49725082 }
49735083 break :result_value result;
49745084 },
4975 .Struct => switch (result_ty.containerLayout()) {
5085 .Struct => switch (result_ty.containerLayout(mod)) {
49765086 .Packed => {
4977 if (isByRef(result_ty, func.target)) {
5087 if (isByRef(result_ty, mod)) {
49785088 return func.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{});
49795089 }
4980 const struct_obj = result_ty.castTag(.@"struct").?.data;
5090 const struct_obj = mod.typeToStruct(result_ty).?;
49815091 const fields = struct_obj.fields.values();
49825092 const backing_type = struct_obj.backing_int_ty;
49835093
49845094 // ensure the result is zero'd
49855095 const result = try func.allocLocal(backing_type);
4986 if (struct_obj.backing_int_ty.bitSize(func.target) <= 32)
5096 if (struct_obj.backing_int_ty.bitSize(mod) <= 32)
49875097 try func.addImm32(0)
49885098 else
49895099 try func.addImm64(0);
......@@ -4992,20 +5102,16 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
49925102 var current_bit: u16 = 0;
49935103 for (elements, 0..) |elem, elem_index| {
49945104 const field = fields[elem_index];
4995 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
5105 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
49965106
4997 const shift_val = if (struct_obj.backing_int_ty.bitSize(func.target) <= 32)
5107 const shift_val = if (struct_obj.backing_int_ty.bitSize(mod) <= 32)
49985108 WValue{ .imm32 = current_bit }
49995109 else
50005110 WValue{ .imm64 = current_bit };
50015111
50025112 const value = try func.resolveInst(elem);
5003 const value_bit_size = @intCast(u16, field.ty.bitSize(func.target));
5004 var int_ty_payload: Type.Payload.Bits = .{
5005 .base = .{ .tag = .int_unsigned },
5006 .data = value_bit_size,
5007 };
5008 const int_ty = Type.initPayload(&int_ty_payload.base);
5113 const value_bit_size = @intCast(u16, field.ty.bitSize(mod));
5114 const int_ty = try mod.intType(.unsigned, value_bit_size);
50095115
50105116 // load our current result on stack so we can perform all transformations
50115117 // using only stack values. Saving the cost of loads and stores.
......@@ -5027,10 +5133,10 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
50275133 const result = try func.allocStack(result_ty);
50285134 const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset
50295135 for (elements, 0..) |elem, elem_index| {
5030 if (result_ty.structFieldValueComptime(elem_index) != null) continue;
5136 if ((try result_ty.structFieldValueComptime(mod, elem_index)) != null) continue;
50315137
5032 const elem_ty = result_ty.structFieldType(elem_index);
5033 const elem_size = @intCast(u32, elem_ty.abiSize(func.target));
5138 const elem_ty = result_ty.structFieldType(elem_index, mod);
5139 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
50345140 const value = try func.resolveInst(elem);
50355141 try func.store(offset, value, elem_ty, 0);
50365142
......@@ -5058,39 +5164,36 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
50585164}
50595165
50605166fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5167 const mod = func.bin_file.base.options.module.?;
50615168 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
50625169 const extra = func.air.extraData(Air.UnionInit, ty_pl.payload).data;
50635170
50645171 const result = result: {
5065 const union_ty = func.air.typeOfIndex(inst);
5066 const layout = union_ty.unionGetLayout(func.target);
5067 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
5172 const union_ty = func.typeOfIndex(inst);
5173 const layout = union_ty.unionGetLayout(mod);
5174 const union_obj = mod.typeToUnion(union_ty).?;
50685175 const field = union_obj.fields.values()[extra.field_index];
50695176 const field_name = union_obj.fields.keys()[extra.field_index];
50705177
50715178 const tag_int = blk: {
5072 const tag_ty = union_ty.unionTagTypeHypothetical();
5073 const enum_field_index = tag_ty.enumFieldIndex(field_name).?;
5074 var tag_val_payload: Value.Payload.U32 = .{
5075 .base = .{ .tag = .enum_field_index },
5076 .data = @intCast(u32, enum_field_index),
5077 };
5078 const tag_val = Value.initPayload(&tag_val_payload.base);
5179 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
5180 const enum_field_index = tag_ty.enumFieldIndex(field_name, mod).?;
5181 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
50795182 break :blk try func.lowerConstant(tag_val, tag_ty);
50805183 };
50815184 if (layout.payload_size == 0) {
50825185 if (layout.tag_size == 0) {
50835186 break :result WValue{ .none = {} };
50845187 }
5085 assert(!isByRef(union_ty, func.target));
5188 assert(!isByRef(union_ty, mod));
50865189 break :result tag_int;
50875190 }
50885191
5089 if (isByRef(union_ty, func.target)) {
5192 if (isByRef(union_ty, mod)) {
50905193 const result_ptr = try func.allocStack(union_ty);
50915194 const payload = try func.resolveInst(extra.init);
50925195 if (layout.tag_align >= layout.payload_align) {
5093 if (isByRef(field.ty, func.target)) {
5196 if (isByRef(field.ty, mod)) {
50945197 const payload_ptr = try func.buildPointerOffset(result_ptr, layout.tag_size, .new);
50955198 try func.store(payload_ptr, payload, field.ty, 0);
50965199 } else {
......@@ -5114,26 +5217,14 @@ fn airUnionInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51145217 break :result result_ptr;
51155218 } else {
51165219 const operand = try func.resolveInst(extra.init);
5117 var payload: Type.Payload.Bits = .{
5118 .base = .{ .tag = .int_unsigned },
5119 .data = @intCast(u16, union_ty.bitSize(func.target)),
5120 };
5121 const union_int_type = Type.initPayload(&payload.base);
5122 if (field.ty.zigTypeTag() == .Float) {
5123 var int_payload: Type.Payload.Bits = .{
5124 .base = .{ .tag = .int_unsigned },
5125 .data = @intCast(u16, field.ty.bitSize(func.target)),
5126 };
5127 const int_type = Type.initPayload(&int_payload.base);
5220 const union_int_type = try mod.intType(.unsigned, @intCast(u16, union_ty.bitSize(mod)));
5221 if (field.ty.zigTypeTag(mod) == .Float) {
5222 const int_type = try mod.intType(.unsigned, @intCast(u16, field.ty.bitSize(mod)));
51285223 const bitcasted = try func.bitcast(field.ty, int_type, operand);
51295224 const casted = try func.trunc(bitcasted, int_type, union_int_type);
51305225 break :result try casted.toLocal(func, field.ty);
5131 } else if (field.ty.isPtrAtRuntime()) {
5132 var int_payload: Type.Payload.Bits = .{
5133 .base = .{ .tag = .int_unsigned },
5134 .data = @intCast(u16, field.ty.bitSize(func.target)),
5135 };
5136 const int_type = Type.initPayload(&int_payload.base);
5226 } else if (field.ty.isPtrAtRuntime(mod)) {
5227 const int_type = try mod.intType(.unsigned, @intCast(u16, field.ty.bitSize(mod)));
51375228 const casted = try func.intcast(operand, int_type, union_int_type);
51385229 break :result try casted.toLocal(func, field.ty);
51395230 }
......@@ -5153,7 +5244,7 @@ fn airPrefetch(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51535244fn airWasmMemorySize(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
51545245 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
51555246
5156 const result = try func.allocLocal(func.air.typeOfIndex(inst));
5247 const result = try func.allocLocal(func.typeOfIndex(inst));
51575248 try func.addLabel(.memory_size, pl_op.payload);
51585249 try func.addLabel(.local_set, result.local.value);
51595250 func.finishAir(inst, result, &.{pl_op.operand});
......@@ -5163,7 +5254,7 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {
51635254 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
51645255
51655256 const operand = try func.resolveInst(pl_op.operand);
5166 const result = try func.allocLocal(func.air.typeOfIndex(inst));
5257 const result = try func.allocLocal(func.typeOfIndex(inst));
51675258 try func.emitWValue(operand);
51685259 try func.addLabel(.memory_grow, pl_op.payload);
51695260 try func.addLabel(.local_set, result.local.value);
......@@ -5171,14 +5262,14 @@ fn airWasmMemoryGrow(func: *CodeGen, inst: Air.Inst.Index) !void {
51715262}
51725263
51735264fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
5174 assert(operand_ty.hasRuntimeBitsIgnoreComptime());
5265 const mod = func.bin_file.base.options.module.?;
5266 assert(operand_ty.hasRuntimeBitsIgnoreComptime(mod));
51755267 assert(op == .eq or op == .neq);
5176 var buf: Type.Payload.ElemType = undefined;
5177 const payload_ty = operand_ty.optionalChild(&buf);
5268 const payload_ty = operand_ty.optionalChild(mod);
51785269
51795270 // We store the final result in here that will be validated
51805271 // if the optional is truly equal.
5181 var result = try func.ensureAllocLocal(Type.initTag(.i32));
5272 var result = try func.ensureAllocLocal(Type.i32);
51825273 defer result.free(func);
51835274
51845275 try func.startBlock(.block, wasm.block_empty);
......@@ -5189,7 +5280,7 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:
51895280
51905281 _ = try func.load(lhs, payload_ty, 0);
51915282 _ = try func.load(rhs, payload_ty, 0);
5192 const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, func.target) });
5283 const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, mod) });
51935284 try func.addTag(Mir.Inst.Tag.fromOpcode(opcode));
51945285 try func.addLabel(.br_if, 0);
51955286
......@@ -5207,10 +5298,11 @@ fn cmpOptionals(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op:
52075298/// NOTE: Leaves the result of the comparison on top of the stack.
52085299/// TODO: Lower this to compiler_rt call when bitsize > 128
52095300fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue {
5210 assert(operand_ty.abiSize(func.target) >= 16);
5301 const mod = func.bin_file.base.options.module.?;
5302 assert(operand_ty.abiSize(mod) >= 16);
52115303 assert(!(lhs != .stack and rhs == .stack));
5212 if (operand_ty.bitSize(func.target) > 128) {
5213 return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(func.target)});
5304 if (operand_ty.bitSize(mod) > 128) {
5305 return func.fail("TODO: Support cmpBigInt for integer bitsize: '{d}'", .{operand_ty.bitSize(mod)});
52145306 }
52155307
52165308 var lhs_high_bit = try (try func.load(lhs, Type.u64, 0)).toLocal(func, Type.u64);
......@@ -5233,7 +5325,7 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std
52335325 }
52345326 },
52355327 else => {
5236 const ty = if (operand_ty.isSignedInt()) Type.i64 else Type.u64;
5328 const ty = if (operand_ty.isSignedInt(mod)) Type.i64 else Type.u64;
52375329 // leave those value on top of the stack for '.select'
52385330 const lhs_low_bit = try func.load(lhs, Type.u64, 8);
52395331 const rhs_low_bit = try func.load(rhs, Type.u64, 8);
......@@ -5248,10 +5340,11 @@ fn cmpBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std
52485340}
52495341
52505342fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5343 const mod = func.bin_file.base.options.module.?;
52515344 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
5252 const un_ty = func.air.typeOf(bin_op.lhs).childType();
5253 const tag_ty = func.air.typeOf(bin_op.rhs);
5254 const layout = un_ty.unionGetLayout(func.target);
5345 const un_ty = func.typeOf(bin_op.lhs).childType(mod);
5346 const tag_ty = func.typeOf(bin_op.rhs);
5347 const layout = un_ty.unionGetLayout(mod);
52555348 if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ bin_op.lhs, bin_op.rhs });
52565349
52575350 const union_ptr = try func.resolveInst(bin_op.lhs);
......@@ -5271,11 +5364,12 @@ fn airSetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
52715364}
52725365
52735366fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5367 const mod = func.bin_file.base.options.module.?;
52745368 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
52755369
5276 const un_ty = func.air.typeOf(ty_op.operand);
5277 const tag_ty = func.air.typeOfIndex(inst);
5278 const layout = un_ty.unionGetLayout(func.target);
5370 const un_ty = func.typeOf(ty_op.operand);
5371 const tag_ty = func.typeOfIndex(inst);
5372 const layout = un_ty.unionGetLayout(mod);
52795373 if (layout.tag_size == 0) return func.finishAir(inst, .none, &.{ty_op.operand});
52805374
52815375 const operand = try func.resolveInst(ty_op.operand);
......@@ -5292,9 +5386,9 @@ fn airGetUnionTag(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
52925386fn airFpext(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
52935387 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
52945388
5295 const dest_ty = func.air.typeOfIndex(inst);
5389 const dest_ty = func.typeOfIndex(inst);
52965390 const operand = try func.resolveInst(ty_op.operand);
5297 const extended = try func.fpext(operand, func.air.typeOf(ty_op.operand), dest_ty);
5391 const extended = try func.fpext(operand, func.typeOf(ty_op.operand), dest_ty);
52985392 const result = try extended.toLocal(func, dest_ty);
52995393 func.finishAir(inst, result, &.{ty_op.operand});
53005394}
......@@ -5313,7 +5407,7 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
53135407 // call __extendhfsf2(f16) f32
53145408 const f32_result = try func.callIntrinsic(
53155409 "__extendhfsf2",
5316 &.{Type.f16},
5410 &.{.f16_type},
53175411 Type.f32,
53185412 &.{operand},
53195413 );
......@@ -5331,15 +5425,15 @@ fn fpext(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerError!
53315425 target_util.compilerRtFloatAbbrev(wanted_bits),
53325426 }) catch unreachable;
53335427
5334 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});
5428 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
53355429}
53365430
53375431fn airFptrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
53385432 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
53395433
5340 const dest_ty = func.air.typeOfIndex(inst);
5434 const dest_ty = func.typeOfIndex(inst);
53415435 const operand = try func.resolveInst(ty_op.operand);
5342 const truncated = try func.fptrunc(operand, func.air.typeOf(ty_op.operand), dest_ty);
5436 const truncated = try func.fptrunc(operand, func.typeOf(ty_op.operand), dest_ty);
53435437 const result = try truncated.toLocal(func, dest_ty);
53445438 func.finishAir(inst, result, &.{ty_op.operand});
53455439}
......@@ -5362,7 +5456,7 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
53625456 } else operand;
53635457
53645458 // call __truncsfhf2(f32) f16
5365 return func.callIntrinsic("__truncsfhf2", &.{Type.f32}, Type.f16, &.{op});
5459 return func.callIntrinsic("__truncsfhf2", &.{.f32_type}, Type.f16, &.{op});
53665460 }
53675461
53685462 var fn_name_buf: [12]u8 = undefined;
......@@ -5371,14 +5465,15 @@ fn fptrunc(func: *CodeGen, operand: WValue, given: Type, wanted: Type) InnerErro
53715465 target_util.compilerRtFloatAbbrev(wanted_bits),
53725466 }) catch unreachable;
53735467
5374 return func.callIntrinsic(fn_name, &.{given}, wanted, &.{operand});
5468 return func.callIntrinsic(fn_name, &.{given.ip_index}, wanted, &.{operand});
53755469}
53765470
53775471fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5472 const mod = func.bin_file.base.options.module.?;
53785473 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
53795474
5380 const err_set_ty = func.air.typeOf(ty_op.operand).childType();
5381 const payload_ty = err_set_ty.errorUnionPayload();
5475 const err_set_ty = func.typeOf(ty_op.operand).childType(mod);
5476 const payload_ty = err_set_ty.errorUnionPayload(mod);
53825477 const operand = try func.resolveInst(ty_op.operand);
53835478
53845479 // set error-tag to '0' to annotate error union is non-error
......@@ -5386,26 +5481,27 @@ fn airErrUnionPayloadPtrSet(func: *CodeGen, inst: Air.Inst.Index) InnerError!voi
53865481 operand,
53875482 .{ .imm32 = 0 },
53885483 Type.anyerror,
5389 @intCast(u32, errUnionErrorOffset(payload_ty, func.target)),
5484 @intCast(u32, errUnionErrorOffset(payload_ty, mod)),
53905485 );
53915486
53925487 const result = result: {
5393 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
5488 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
53945489 break :result func.reuseOperand(ty_op.operand, operand);
53955490 }
53965491
5397 break :result try func.buildPointerOffset(operand, @intCast(u32, errUnionPayloadOffset(payload_ty, func.target)), .new);
5492 break :result try func.buildPointerOffset(operand, @intCast(u32, errUnionPayloadOffset(payload_ty, mod)), .new);
53985493 };
53995494 func.finishAir(inst, result, &.{ty_op.operand});
54005495}
54015496
54025497fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5498 const mod = func.bin_file.base.options.module.?;
54035499 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
54045500 const extra = func.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
54055501
54065502 const field_ptr = try func.resolveInst(extra.field_ptr);
5407 const parent_ty = func.air.getRefType(ty_pl.ty).childType();
5408 const field_offset = parent_ty.structFieldOffset(extra.field_index, func.target);
5503 const parent_ty = func.air.getRefType(ty_pl.ty).childType(mod);
5504 const field_offset = parent_ty.structFieldOffset(extra.field_index, mod);
54095505
54105506 const result = if (field_offset != 0) result: {
54115507 const base = try func.buildPointerOffset(field_ptr, 0, .new);
......@@ -5420,7 +5516,8 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
54205516}
54215517
54225518fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue {
5423 if (ptr_ty.isSlice()) {
5519 const mod = func.bin_file.base.options.module.?;
5520 if (ptr_ty.isSlice(mod)) {
54245521 return func.slicePtr(ptr);
54255522 } else {
54265523 return ptr;
......@@ -5428,25 +5525,26 @@ fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue
54285525}
54295526
54305527fn airMemcpy(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5528 const mod = func.bin_file.base.options.module.?;
54315529 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
54325530 const dst = try func.resolveInst(bin_op.lhs);
5433 const dst_ty = func.air.typeOf(bin_op.lhs);
5434 const ptr_elem_ty = dst_ty.childType();
5531 const dst_ty = func.typeOf(bin_op.lhs);
5532 const ptr_elem_ty = dst_ty.childType(mod);
54355533 const src = try func.resolveInst(bin_op.rhs);
5436 const src_ty = func.air.typeOf(bin_op.rhs);
5437 const len = switch (dst_ty.ptrSize()) {
5534 const src_ty = func.typeOf(bin_op.rhs);
5535 const len = switch (dst_ty.ptrSize(mod)) {
54385536 .Slice => blk: {
54395537 const slice_len = try func.sliceLen(dst);
5440 if (ptr_elem_ty.abiSize(func.target) != 1) {
5538 if (ptr_elem_ty.abiSize(mod) != 1) {
54415539 try func.emitWValue(slice_len);
5442 try func.emitWValue(.{ .imm32 = @intCast(u32, ptr_elem_ty.abiSize(func.target)) });
5540 try func.emitWValue(.{ .imm32 = @intCast(u32, ptr_elem_ty.abiSize(mod)) });
54435541 try func.addTag(.i32_mul);
54445542 try func.addLabel(.local_set, slice_len.local.value);
54455543 }
54465544 break :blk slice_len;
54475545 },
54485546 .One => @as(WValue, .{
5449 .imm32 = @intCast(u32, ptr_elem_ty.arrayLen() * ptr_elem_ty.childType().abiSize(func.target)),
5547 .imm32 = @intCast(u32, ptr_elem_ty.arrayLen(mod) * ptr_elem_ty.childType(mod).abiSize(mod)),
54505548 }),
54515549 .C, .Many => unreachable,
54525550 };
......@@ -5467,17 +5565,18 @@ fn airRetAddr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
54675565}
54685566
54695567fn airPopcount(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5568 const mod = func.bin_file.base.options.module.?;
54705569 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
54715570
54725571 const operand = try func.resolveInst(ty_op.operand);
5473 const op_ty = func.air.typeOf(ty_op.operand);
5474 const result_ty = func.air.typeOfIndex(inst);
5572 const op_ty = func.typeOf(ty_op.operand);
5573 const result_ty = func.typeOfIndex(inst);
54755574
5476 if (op_ty.zigTypeTag() == .Vector) {
5575 if (op_ty.zigTypeTag(mod) == .Vector) {
54775576 return func.fail("TODO: Implement @popCount for vectors", .{});
54785577 }
54795578
5480 const int_info = op_ty.intInfo(func.target);
5579 const int_info = op_ty.intInfo(mod);
54815580 const bits = int_info.bits;
54825581 const wasm_bits = toWasmBits(bits) orelse {
54835582 return func.fail("TODO: Implement @popCount for integers with bitsize '{d}'", .{bits});
......@@ -5526,8 +5625,9 @@ fn airErrorName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
55265625 // As the names are global and the slice elements are constant, we do not have
55275626 // to make a copy of the ptr+value but can point towards them directly.
55285627 const error_table_symbol = try func.bin_file.getErrorTableSymbol();
5529 const name_ty = Type.initTag(.const_slice_u8_sentinel_0);
5530 const abi_size = name_ty.abiSize(func.target);
5628 const name_ty = Type.slice_const_u8_sentinel_0;
5629 const mod = func.bin_file.base.options.module.?;
5630 const abi_size = name_ty.abiSize(mod);
55315631
55325632 const error_name_value: WValue = .{ .memory = error_table_symbol }; // emitting this will create a relocation
55335633 try func.emitWValue(error_name_value);
......@@ -5565,20 +5665,21 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
55655665
55665666 const lhs_op = try func.resolveInst(extra.lhs);
55675667 const rhs_op = try func.resolveInst(extra.rhs);
5568 const lhs_ty = func.air.typeOf(extra.lhs);
5668 const lhs_ty = func.typeOf(extra.lhs);
5669 const mod = func.bin_file.base.options.module.?;
55695670
5570 if (lhs_ty.zigTypeTag() == .Vector) {
5671 if (lhs_ty.zigTypeTag(mod) == .Vector) {
55715672 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});
55725673 }
55735674
5574 const int_info = lhs_ty.intInfo(func.target);
5675 const int_info = lhs_ty.intInfo(mod);
55755676 const is_signed = int_info.signedness == .signed;
55765677 const wasm_bits = toWasmBits(int_info.bits) orelse {
55775678 return func.fail("TODO: Implement {{add/sub}}_with_overflow for integer bitsize: {d}", .{int_info.bits});
55785679 };
55795680
55805681 if (wasm_bits == 128) {
5581 const result = try func.addSubWithOverflowBigInt(lhs_op, rhs_op, lhs_ty, func.air.typeOfIndex(inst), op);
5682 const result = try func.addSubWithOverflowBigInt(lhs_op, rhs_op, lhs_ty, func.typeOfIndex(inst), op);
55825683 return func.finishAir(inst, result, &.{ extra.lhs, extra.rhs });
55835684 }
55845685
......@@ -5628,17 +5729,18 @@ fn airAddSubWithOverflow(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerErro
56285729 var overflow_local = try overflow_bit.toLocal(func, Type.u32);
56295730 defer overflow_local.free(func);
56305731
5631 const result_ptr = try func.allocStack(func.air.typeOfIndex(inst));
5732 const result_ptr = try func.allocStack(func.typeOfIndex(inst));
56325733 try func.store(result_ptr, result, lhs_ty, 0);
5633 const offset = @intCast(u32, lhs_ty.abiSize(func.target));
5634 try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset);
5734 const offset = @intCast(u32, lhs_ty.abiSize(mod));
5735 try func.store(result_ptr, overflow_local, Type.u1, offset);
56355736
56365737 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
56375738}
56385739
56395740fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, result_ty: Type, op: Op) InnerError!WValue {
5741 const mod = func.bin_file.base.options.module.?;
56405742 assert(op == .add or op == .sub);
5641 const int_info = ty.intInfo(func.target);
5743 const int_info = ty.intInfo(mod);
56425744 const is_signed = int_info.signedness == .signed;
56435745 if (int_info.bits != 128) {
56445746 return func.fail("TODO: Implement @{{add/sub}}WithOverflow for integer bitsize '{d}'", .{int_info.bits});
......@@ -5689,31 +5791,32 @@ fn addSubWithOverflowBigInt(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type,
56895791
56905792 break :blk WValue{ .stack = {} };
56915793 };
5692 var overflow_local = try overflow_bit.toLocal(func, Type.initTag(.u1));
5794 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
56935795 defer overflow_local.free(func);
56945796
56955797 const result_ptr = try func.allocStack(result_ty);
56965798 try func.store(result_ptr, high_op_res, Type.u64, 0);
56975799 try func.store(result_ptr, tmp_op, Type.u64, 8);
5698 try func.store(result_ptr, overflow_local, Type.initTag(.u1), 16);
5800 try func.store(result_ptr, overflow_local, Type.u1, 16);
56995801
57005802 return result_ptr;
57015803}
57025804
57035805fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
5806 const mod = func.bin_file.base.options.module.?;
57045807 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
57055808 const extra = func.air.extraData(Air.Bin, ty_pl.payload).data;
57065809
57075810 const lhs = try func.resolveInst(extra.lhs);
57085811 const rhs = try func.resolveInst(extra.rhs);
5709 const lhs_ty = func.air.typeOf(extra.lhs);
5710 const rhs_ty = func.air.typeOf(extra.rhs);
5812 const lhs_ty = func.typeOf(extra.lhs);
5813 const rhs_ty = func.typeOf(extra.rhs);
57115814
5712 if (lhs_ty.zigTypeTag() == .Vector) {
5815 if (lhs_ty.zigTypeTag(mod) == .Vector) {
57135816 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});
57145817 }
57155818
5716 const int_info = lhs_ty.intInfo(func.target);
5819 const int_info = lhs_ty.intInfo(mod);
57175820 const is_signed = int_info.signedness == .signed;
57185821 const wasm_bits = toWasmBits(int_info.bits) orelse {
57195822 return func.fail("TODO: Implement shl_with_overflow for integer bitsize: {d}", .{int_info.bits});
......@@ -5721,7 +5824,7 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57215824
57225825 // Ensure rhs is coerced to lhs as they must have the same WebAssembly types
57235826 // before we can perform any binary operation.
5724 const rhs_wasm_bits = toWasmBits(rhs_ty.intInfo(func.target).bits).?;
5827 const rhs_wasm_bits = toWasmBits(rhs_ty.intInfo(mod).bits).?;
57255828 const rhs_final = if (wasm_bits != rhs_wasm_bits) blk: {
57265829 const rhs_casted = try func.intcast(rhs, rhs_ty, lhs_ty);
57275830 break :blk try rhs_casted.toLocal(func, lhs_ty);
......@@ -5745,13 +5848,13 @@ fn airShlWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57455848 const shr = try func.binOp(result, rhs_final, lhs_ty, .shr);
57465849 break :blk try func.cmp(.{ .stack = {} }, shr, lhs_ty, .neq);
57475850 };
5748 var overflow_local = try overflow_bit.toLocal(func, Type.initTag(.u1));
5851 var overflow_local = try overflow_bit.toLocal(func, Type.u1);
57495852 defer overflow_local.free(func);
57505853
5751 const result_ptr = try func.allocStack(func.air.typeOfIndex(inst));
5854 const result_ptr = try func.allocStack(func.typeOfIndex(inst));
57525855 try func.store(result_ptr, result, lhs_ty, 0);
5753 const offset = @intCast(u32, lhs_ty.abiSize(func.target));
5754 try func.store(result_ptr, overflow_local, Type.initTag(.u1), offset);
5856 const offset = @intCast(u32, lhs_ty.abiSize(mod));
5857 try func.store(result_ptr, overflow_local, Type.u1, offset);
57555858
57565859 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
57575860}
......@@ -5762,18 +5865,19 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
57625865
57635866 const lhs = try func.resolveInst(extra.lhs);
57645867 const rhs = try func.resolveInst(extra.rhs);
5765 const lhs_ty = func.air.typeOf(extra.lhs);
5868 const lhs_ty = func.typeOf(extra.lhs);
5869 const mod = func.bin_file.base.options.module.?;
57665870
5767 if (lhs_ty.zigTypeTag() == .Vector) {
5871 if (lhs_ty.zigTypeTag(mod) == .Vector) {
57685872 return func.fail("TODO: Implement overflow arithmetic for vectors", .{});
57695873 }
57705874
57715875 // We store the bit if it's overflowed or not in this. As it's zero-initialized
57725876 // we only need to update it if an overflow (or underflow) occurred.
5773 var overflow_bit = try func.ensureAllocLocal(Type.initTag(.u1));
5877 var overflow_bit = try func.ensureAllocLocal(Type.u1);
57745878 defer overflow_bit.free(func);
57755879
5776 const int_info = lhs_ty.intInfo(func.target);
5880 const int_info = lhs_ty.intInfo(mod);
57775881 const wasm_bits = toWasmBits(int_info.bits) orelse {
57785882 return func.fail("TODO: Implement `@mulWithOverflow` for integer bitsize: {d}", .{int_info.bits});
57795883 };
......@@ -5827,7 +5931,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58275931 try func.addLabel(.local_set, overflow_bit.local.value);
58285932 break :blk try func.wrapOperand(bin_op, lhs_ty);
58295933 } else if (int_info.bits == 64 and int_info.signedness == .unsigned) blk: {
5830 const new_ty = Type.initTag(.u128);
5934 const new_ty = Type.u128;
58315935 var lhs_upcast = try (try func.intcast(lhs, lhs_ty, new_ty)).toLocal(func, lhs_ty);
58325936 defer lhs_upcast.free(func);
58335937 var rhs_upcast = try (try func.intcast(rhs, lhs_ty, new_ty)).toLocal(func, lhs_ty);
......@@ -5847,8 +5951,8 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58475951
58485952 const bin_op = try func.callIntrinsic(
58495953 "__multi3",
5850 &[_]Type{Type.i64} ** 4,
5851 Type.initTag(.i128),
5954 &[_]InternPool.Index{.i64_type} ** 4,
5955 Type.i128,
58525956 &.{ lhs, lhs_shifted, rhs, rhs_shifted },
58535957 );
58545958 const res = try func.allocLocal(lhs_ty);
......@@ -5871,20 +5975,20 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
58715975
58725976 const mul1 = try func.callIntrinsic(
58735977 "__multi3",
5874 &[_]Type{Type.i64} ** 4,
5875 Type.initTag(.i128),
5978 &[_]InternPool.Index{.i64_type} ** 4,
5979 Type.i128,
58765980 &.{ lhs_lsb, zero, rhs_msb, zero },
58775981 );
58785982 const mul2 = try func.callIntrinsic(
58795983 "__multi3",
5880 &[_]Type{Type.i64} ** 4,
5881 Type.initTag(.i128),
5984 &[_]InternPool.Index{.i64_type} ** 4,
5985 Type.i128,
58825986 &.{ rhs_lsb, zero, lhs_msb, zero },
58835987 );
58845988 const mul3 = try func.callIntrinsic(
58855989 "__multi3",
5886 &[_]Type{Type.i64} ** 4,
5887 Type.initTag(.i128),
5990 &[_]InternPool.Index{.i64_type} ** 4,
5991 Type.i128,
58885992 &.{ lhs_msb, zero, rhs_msb, zero },
58895993 );
58905994
......@@ -5912,7 +6016,7 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59126016 _ = try func.binOp(lsb_or, mul_add_lt, Type.bool, .@"or");
59136017 try func.addLabel(.local_set, overflow_bit.local.value);
59146018
5915 const tmp_result = try func.allocStack(Type.initTag(.u128));
6019 const tmp_result = try func.allocStack(Type.u128);
59166020 try func.emitWValue(tmp_result);
59176021 const mul3_msb = try func.load(mul3, Type.u64, 0);
59186022 try func.store(.stack, mul3_msb, Type.u64, tmp_result.offset());
......@@ -5922,23 +6026,24 @@ fn airMulWithOverflow(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59226026 var bin_op_local = try bin_op.toLocal(func, lhs_ty);
59236027 defer bin_op_local.free(func);
59246028
5925 const result_ptr = try func.allocStack(func.air.typeOfIndex(inst));
6029 const result_ptr = try func.allocStack(func.typeOfIndex(inst));
59266030 try func.store(result_ptr, bin_op_local, lhs_ty, 0);
5927 const offset = @intCast(u32, lhs_ty.abiSize(func.target));
5928 try func.store(result_ptr, overflow_bit, Type.initTag(.u1), offset);
6031 const offset = @intCast(u32, lhs_ty.abiSize(mod));
6032 try func.store(result_ptr, overflow_bit, Type.u1, offset);
59296033
59306034 func.finishAir(inst, result_ptr, &.{ extra.lhs, extra.rhs });
59316035}
59326036
59336037fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerError!void {
6038 const mod = func.bin_file.base.options.module.?;
59346039 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
59356040
5936 const ty = func.air.typeOfIndex(inst);
5937 if (ty.zigTypeTag() == .Vector) {
6041 const ty = func.typeOfIndex(inst);
6042 if (ty.zigTypeTag(mod) == .Vector) {
59386043 return func.fail("TODO: `@maximum` and `@minimum` for vectors", .{});
59396044 }
59406045
5941 if (ty.abiSize(func.target) > 16) {
6046 if (ty.abiSize(mod) > 16) {
59426047 return func.fail("TODO: `@maximum` and `@minimum` for types larger than 16 bytes", .{});
59436048 }
59446049
......@@ -5954,18 +6059,19 @@ fn airMaxMin(func: *CodeGen, inst: Air.Inst.Index, op: enum { max, min }) InnerE
59546059 try func.addTag(.select);
59556060
59566061 // store result in local
5957 const result_ty = if (isByRef(ty, func.target)) Type.u32 else ty;
6062 const result_ty = if (isByRef(ty, mod)) Type.u32 else ty;
59586063 const result = try func.allocLocal(result_ty);
59596064 try func.addLabel(.local_set, result.local.value);
59606065 func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
59616066}
59626067
59636068fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6069 const mod = func.bin_file.base.options.module.?;
59646070 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
59656071 const bin_op = func.air.extraData(Air.Bin, pl_op.payload).data;
59666072
5967 const ty = func.air.typeOfIndex(inst);
5968 if (ty.zigTypeTag() == .Vector) {
6073 const ty = func.typeOfIndex(inst);
6074 if (ty.zigTypeTag(mod) == .Vector) {
59696075 return func.fail("TODO: `@mulAdd` for vectors", .{});
59706076 }
59716077
......@@ -5980,7 +6086,7 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59806086 // call to compiler-rt `fn fmaf(f32, f32, f32) f32`
59816087 var result = try func.callIntrinsic(
59826088 "fmaf",
5983 &.{ Type.f32, Type.f32, Type.f32 },
6089 &.{ .f32_type, .f32_type, .f32_type },
59846090 Type.f32,
59856091 &.{ rhs_ext, lhs_ext, addend_ext },
59866092 );
......@@ -5994,16 +6100,17 @@ fn airMulAdd(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
59946100}
59956101
59966102fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6103 const mod = func.bin_file.base.options.module.?;
59976104 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
59986105
5999 const ty = func.air.typeOf(ty_op.operand);
6000 const result_ty = func.air.typeOfIndex(inst);
6001 if (ty.zigTypeTag() == .Vector) {
6106 const ty = func.typeOf(ty_op.operand);
6107 const result_ty = func.typeOfIndex(inst);
6108 if (ty.zigTypeTag(mod) == .Vector) {
60026109 return func.fail("TODO: `@clz` for vectors", .{});
60036110 }
60046111
60056112 const operand = try func.resolveInst(ty_op.operand);
6006 const int_info = ty.intInfo(func.target);
6113 const int_info = ty.intInfo(mod);
60076114 const wasm_bits = toWasmBits(int_info.bits) orelse {
60086115 return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits});
60096116 };
......@@ -6046,17 +6153,18 @@ fn airClz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
60466153}
60476154
60486155fn airCtz(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6156 const mod = func.bin_file.base.options.module.?;
60496157 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
60506158
6051 const ty = func.air.typeOf(ty_op.operand);
6052 const result_ty = func.air.typeOfIndex(inst);
6159 const ty = func.typeOf(ty_op.operand);
6160 const result_ty = func.typeOfIndex(inst);
60536161
6054 if (ty.zigTypeTag() == .Vector) {
6162 if (ty.zigTypeTag(mod) == .Vector) {
60556163 return func.fail("TODO: `@ctz` for vectors", .{});
60566164 }
60576165
60586166 const operand = try func.resolveInst(ty_op.operand);
6059 const int_info = ty.intInfo(func.target);
6167 const int_info = ty.intInfo(mod);
60606168 const wasm_bits = toWasmBits(int_info.bits) orelse {
60616169 return func.fail("TODO: `@clz` for integers with bitsize '{d}'", .{int_info.bits});
60626170 };
......@@ -6113,7 +6221,7 @@ fn airDbgVar(func: *CodeGen, inst: Air.Inst.Index, is_ptr: bool) !void {
61136221 if (func.debug_output != .dwarf) return func.finishAir(inst, .none, &.{});
61146222
61156223 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
6116 const ty = func.air.typeOf(pl_op.operand);
6224 const ty = func.typeOf(pl_op.operand);
61176225 const operand = try func.resolveInst(pl_op.operand);
61186226
61196227 log.debug("airDbgVar: %{d}: {}, {}", .{ inst, ty.fmtDebug(), operand });
......@@ -6151,17 +6259,18 @@ fn airTry(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
61516259 const err_union = try func.resolveInst(pl_op.operand);
61526260 const extra = func.air.extraData(Air.Try, pl_op.payload);
61536261 const body = func.air.extra[extra.end..][0..extra.data.body_len];
6154 const err_union_ty = func.air.typeOf(pl_op.operand);
6262 const err_union_ty = func.typeOf(pl_op.operand);
61556263 const result = try lowerTry(func, inst, err_union, body, err_union_ty, false);
61566264 func.finishAir(inst, result, &.{pl_op.operand});
61576265}
61586266
61596267fn airTryPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6268 const mod = func.bin_file.base.options.module.?;
61606269 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
61616270 const extra = func.air.extraData(Air.TryPtr, ty_pl.payload);
61626271 const err_union_ptr = try func.resolveInst(extra.data.ptr);
61636272 const body = func.air.extra[extra.end..][0..extra.data.body_len];
6164 const err_union_ty = func.air.typeOf(extra.data.ptr).childType();
6273 const err_union_ty = func.typeOf(extra.data.ptr).childType(mod);
61656274 const result = try lowerTry(func, inst, err_union_ptr, body, err_union_ty, true);
61666275 func.finishAir(inst, result, &.{extra.data.ptr});
61676276}
......@@ -6174,24 +6283,25 @@ fn lowerTry(
61746283 err_union_ty: Type,
61756284 operand_is_ptr: bool,
61766285) InnerError!WValue {
6286 const mod = func.bin_file.base.options.module.?;
61776287 if (operand_is_ptr) {
61786288 return func.fail("TODO: lowerTry for pointers", .{});
61796289 }
61806290
6181 const pl_ty = err_union_ty.errorUnionPayload();
6182 const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime();
6291 const pl_ty = err_union_ty.errorUnionPayload(mod);
6292 const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(mod);
61836293
6184 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
6294 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
61856295 // Block we can jump out of when error is not set
61866296 try func.startBlock(.block, wasm.block_empty);
61876297
61886298 // check if the error tag is set for the error union.
61896299 try func.emitWValue(err_union);
61906300 if (pl_has_bits) {
6191 const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, func.target));
6301 const err_offset = @intCast(u32, errUnionErrorOffset(pl_ty, mod));
61926302 try func.addMemArg(.i32_load16_u, .{
61936303 .offset = err_union.offset() + err_offset,
6194 .alignment = Type.anyerror.abiAlignment(func.target),
6304 .alignment = Type.anyerror.abiAlignment(mod),
61956305 });
61966306 }
61976307 try func.addTag(.i32_eqz);
......@@ -6213,8 +6323,8 @@ fn lowerTry(
62136323 return WValue{ .none = {} };
62146324 }
62156325
6216 const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, func.target));
6217 if (isByRef(pl_ty, func.target)) {
6326 const pl_offset = @intCast(u32, errUnionPayloadOffset(pl_ty, mod));
6327 if (isByRef(pl_ty, mod)) {
62186328 return buildPointerOffset(func, err_union, pl_offset, .new);
62196329 }
62206330 const payload = try func.load(err_union, pl_ty, pl_offset);
......@@ -6222,15 +6332,16 @@ fn lowerTry(
62226332}
62236333
62246334fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6335 const mod = func.bin_file.base.options.module.?;
62256336 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
62266337
6227 const ty = func.air.typeOfIndex(inst);
6338 const ty = func.typeOfIndex(inst);
62286339 const operand = try func.resolveInst(ty_op.operand);
62296340
6230 if (ty.zigTypeTag() == .Vector) {
6341 if (ty.zigTypeTag(mod) == .Vector) {
62316342 return func.fail("TODO: @byteSwap for vectors", .{});
62326343 }
6233 const int_info = ty.intInfo(func.target);
6344 const int_info = ty.intInfo(mod);
62346345
62356346 // bytes are no-op
62366347 if (int_info.bits == 8) {
......@@ -6292,13 +6403,14 @@ fn airByteSwap(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
62926403}
62936404
62946405fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6406 const mod = func.bin_file.base.options.module.?;
62956407 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
62966408
6297 const ty = func.air.typeOfIndex(inst);
6409 const ty = func.typeOfIndex(inst);
62986410 const lhs = try func.resolveInst(bin_op.lhs);
62996411 const rhs = try func.resolveInst(bin_op.rhs);
63006412
6301 const result = if (ty.isSignedInt())
6413 const result = if (ty.isSignedInt(mod))
63026414 try func.divSigned(lhs, rhs, ty)
63036415 else
63046416 try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);
......@@ -6306,13 +6418,14 @@ fn airDiv(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63066418}
63076419
63086420fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
6421 const mod = func.bin_file.base.options.module.?;
63096422 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
63106423
6311 const ty = func.air.typeOfIndex(inst);
6424 const ty = func.typeOfIndex(inst);
63126425 const lhs = try func.resolveInst(bin_op.lhs);
63136426 const rhs = try func.resolveInst(bin_op.rhs);
63146427
6315 const div_result = if (ty.isSignedInt())
6428 const div_result = if (ty.isSignedInt(mod))
63166429 try func.divSigned(lhs, rhs, ty)
63176430 else
63186431 try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);
......@@ -6328,15 +6441,16 @@ fn airDivTrunc(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63286441fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
63296442 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
63306443
6331 const ty = func.air.typeOfIndex(inst);
6444 const mod = func.bin_file.base.options.module.?;
6445 const ty = func.typeOfIndex(inst);
63326446 const lhs = try func.resolveInst(bin_op.lhs);
63336447 const rhs = try func.resolveInst(bin_op.rhs);
63346448
6335 if (ty.isUnsignedInt()) {
6449 if (ty.isUnsignedInt(mod)) {
63366450 const result = try (try func.binOp(lhs, rhs, ty, .div)).toLocal(func, ty);
63376451 return func.finishAir(inst, result, &.{ bin_op.lhs, bin_op.rhs });
6338 } else if (ty.isSignedInt()) {
6339 const int_bits = ty.intInfo(func.target).bits;
6452 } else if (ty.isSignedInt(mod)) {
6453 const int_bits = ty.intInfo(mod).bits;
63406454 const wasm_bits = toWasmBits(int_bits) orelse {
63416455 return func.fail("TODO: `@divFloor` for signed integers larger than '{d}' bits", .{int_bits});
63426456 };
......@@ -6414,7 +6528,8 @@ fn airDivFloor(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
64146528}
64156529
64166530fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WValue {
6417 const int_bits = ty.intInfo(func.target).bits;
6531 const mod = func.bin_file.base.options.module.?;
6532 const int_bits = ty.intInfo(mod).bits;
64186533 const wasm_bits = toWasmBits(int_bits) orelse {
64196534 return func.fail("TODO: Implement signed division for integers with bitsize '{d}'", .{int_bits});
64206535 };
......@@ -6441,7 +6556,8 @@ fn divSigned(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type) InnerError!WVal
64416556/// Retrieves the absolute value of a signed integer
64426557/// NOTE: Leaves the result value on the stack.
64436558fn signAbsValue(func: *CodeGen, operand: WValue, ty: Type) InnerError!WValue {
6444 const int_bits = ty.intInfo(func.target).bits;
6559 const mod = func.bin_file.base.options.module.?;
6560 const int_bits = ty.intInfo(mod).bits;
64456561 const wasm_bits = toWasmBits(int_bits) orelse {
64466562 return func.fail("TODO: signAbsValue for signed integers larger than '{d}' bits", .{int_bits});
64476563 };
......@@ -6476,11 +6592,12 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
64766592 assert(op == .add or op == .sub);
64776593 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
64786594
6479 const ty = func.air.typeOfIndex(inst);
6595 const mod = func.bin_file.base.options.module.?;
6596 const ty = func.typeOfIndex(inst);
64806597 const lhs = try func.resolveInst(bin_op.lhs);
64816598 const rhs = try func.resolveInst(bin_op.rhs);
64826599
6483 const int_info = ty.intInfo(func.target);
6600 const int_info = ty.intInfo(mod);
64846601 const is_signed = int_info.signedness == .signed;
64856602
64866603 if (int_info.bits > 64) {
......@@ -6523,7 +6640,8 @@ fn airSatBinOp(func: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void {
65236640}
65246641
65256642fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type, op: Op) InnerError!WValue {
6526 const int_info = ty.intInfo(func.target);
6643 const mod = func.bin_file.base.options.module.?;
6644 const int_info = ty.intInfo(mod);
65276645 const wasm_bits = toWasmBits(int_info.bits).?;
65286646 const is_wasm_bits = wasm_bits == int_info.bits;
65296647
......@@ -6588,8 +6706,9 @@ fn signedSat(func: *CodeGen, lhs_operand: WValue, rhs_operand: WValue, ty: Type,
65886706fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
65896707 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
65906708
6591 const ty = func.air.typeOfIndex(inst);
6592 const int_info = ty.intInfo(func.target);
6709 const mod = func.bin_file.base.options.module.?;
6710 const ty = func.typeOfIndex(inst);
6711 const int_info = ty.intInfo(mod);
65936712 const is_signed = int_info.signedness == .signed;
65946713 if (int_info.bits > 64) {
65956714 return func.fail("TODO: Saturating shifting left for integers with bitsize '{d}'", .{int_info.bits});
......@@ -6697,7 +6816,7 @@ fn airShlSat(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
66976816fn callIntrinsic(
66986817 func: *CodeGen,
66996818 name: []const u8,
6700 param_types: []const Type,
6819 param_types: []const InternPool.Index,
67016820 return_type: Type,
67026821 args: []const WValue,
67036822) InnerError!WValue {
......@@ -6707,12 +6826,13 @@ fn callIntrinsic(
67076826 };
67086827
67096828 // Always pass over C-ABI
6710 var func_type = try genFunctype(func.gpa, .C, param_types, return_type, func.target);
6829 const mod = func.bin_file.base.options.module.?;
6830 var func_type = try genFunctype(func.gpa, .C, param_types, return_type, mod);
67116831 defer func_type.deinit(func.gpa);
67126832 const func_type_index = try func.bin_file.putOrGetFuncType(func_type);
67136833 try func.bin_file.addOrUpdateImport(name, symbol_index, null, func_type_index);
67146834
6715 const want_sret_param = firstParamSRet(.C, return_type, func.target);
6835 const want_sret_param = firstParamSRet(.C, return_type, mod);
67166836 // if we want return as first param, we allocate a pointer to stack,
67176837 // and emit it as our first argument
67186838 const sret = if (want_sret_param) blk: {
......@@ -6724,16 +6844,16 @@ fn callIntrinsic(
67246844 // Lower all arguments to the stack before we call our function
67256845 for (args, 0..) |arg, arg_i| {
67266846 assert(!(want_sret_param and arg == .stack));
6727 assert(param_types[arg_i].hasRuntimeBitsIgnoreComptime());
6728 try func.lowerArg(.C, param_types[arg_i], arg);
6847 assert(param_types[arg_i].toType().hasRuntimeBitsIgnoreComptime(mod));
6848 try func.lowerArg(.C, param_types[arg_i].toType(), arg);
67296849 }
67306850
67316851 // Actually call our intrinsic
67326852 try func.addLabel(.call, symbol_index);
67336853
6734 if (!return_type.hasRuntimeBitsIgnoreComptime()) {
6854 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
67356855 return WValue.none;
6736 } else if (return_type.isNoReturn()) {
6856 } else if (return_type.isNoReturn(mod)) {
67376857 try func.addTag(.@"unreachable");
67386858 return WValue.none;
67396859 } else if (want_sret_param) {
......@@ -6746,11 +6866,11 @@ fn callIntrinsic(
67466866fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67476867 const un_op = func.air.instructions.items(.data)[inst].un_op;
67486868 const operand = try func.resolveInst(un_op);
6749 const enum_ty = func.air.typeOf(un_op);
6869 const enum_ty = func.typeOf(un_op);
67506870
67516871 const func_sym_index = try func.getTagNameFunction(enum_ty);
67526872
6753 const result_ptr = try func.allocStack(func.air.typeOfIndex(inst));
6873 const result_ptr = try func.allocStack(func.typeOfIndex(inst));
67546874 try func.lowerToStack(result_ptr);
67556875 try func.emitWValue(operand);
67566876 try func.addLabel(.call, func_sym_index);
......@@ -6759,15 +6879,14 @@ fn airTagName(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
67596879}
67606880
67616881fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
6762 const enum_decl_index = enum_ty.getOwnerDecl();
6763 const module = func.bin_file.base.options.module.?;
6882 const mod = func.bin_file.base.options.module.?;
6883 const enum_decl_index = enum_ty.getOwnerDecl(mod);
67646884
67656885 var arena_allocator = std.heap.ArenaAllocator.init(func.gpa);
67666886 defer arena_allocator.deinit();
67676887 const arena = arena_allocator.allocator();
67686888
6769 const fqn = try module.declPtr(enum_decl_index).getFullyQualifiedName(module);
6770 defer module.gpa.free(fqn);
6889 const fqn = mod.intern_pool.stringToSlice(try mod.declPtr(enum_decl_index).getFullyQualifiedName(mod));
67716890 const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
67726891
67736892 // check if we already generated code for this.
......@@ -6775,10 +6894,9 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
67756894 return loc.index;
67766895 }
67776896
6778 var int_tag_type_buffer: Type.Payload.Bits = undefined;
6779 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
6897 const int_tag_ty = enum_ty.intTagType(mod);
67806898
6781 if (int_tag_ty.bitSize(func.target) > 64) {
6899 if (int_tag_ty.bitSize(mod) > 64) {
67826900 return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{});
67836901 }
67846902
......@@ -6798,36 +6916,22 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
67986916
67996917 // TODO: Make switch implementation generic so we can use a jump table for this when the tags are not sparse.
68006918 // generate an if-else chain for each tag value as well as constant.
6801 for (enum_ty.enumFields().keys(), 0..) |tag_name, field_index| {
6919 for (enum_ty.enumFields(mod), 0..) |tag_name_ip, field_index_usize| {
6920 const field_index = @intCast(u32, field_index_usize);
6921 const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);
68026922 // for each tag name, create an unnamed const,
68036923 // and then get a pointer to its value.
6804 var name_ty_payload: Type.Payload.Len = .{
6805 .base = .{ .tag = .array_u8_sentinel_0 },
6806 .data = @intCast(u64, tag_name.len),
6807 };
6808 const name_ty = Type.initPayload(&name_ty_payload.base);
6809 const string_bytes = &module.string_literal_bytes;
6810 try string_bytes.ensureUnusedCapacity(module.gpa, tag_name.len);
6811 const gop = try module.string_literal_table.getOrPutContextAdapted(module.gpa, tag_name, Module.StringLiteralAdapter{
6812 .bytes = string_bytes,
6813 }, Module.StringLiteralContext{
6814 .bytes = string_bytes,
6924 const name_ty = try mod.arrayType(.{
6925 .len = tag_name.len,
6926 .child = .u8_type,
6927 .sentinel = .zero_u8,
68156928 });
6816 if (!gop.found_existing) {
6817 gop.key_ptr.* = .{
6818 .index = @intCast(u32, string_bytes.items.len),
6819 .len = @intCast(u32, tag_name.len),
6820 };
6821 string_bytes.appendSliceAssumeCapacity(tag_name);
6822 gop.value_ptr.* = .none;
6823 }
6824 var name_val_payload: Value.Payload.StrLit = .{
6825 .base = .{ .tag = .str_lit },
6826 .data = gop.key_ptr.*,
6827 };
6828 const name_val = Value.initPayload(&name_val_payload.base);
6929 const name_val = try mod.intern(.{ .aggregate = .{
6930 .ty = name_ty.toIntern(),
6931 .storage = .{ .bytes = tag_name },
6932 } });
68296933 const tag_sym_index = try func.bin_file.lowerUnnamedConst(
6830 .{ .ty = name_ty, .val = name_val },
6934 .{ .ty = name_ty, .val = name_val.toValue() },
68316935 enum_decl_index,
68326936 );
68336937
......@@ -6839,11 +6943,8 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
68396943 try writer.writeByte(std.wasm.opcode(.local_get));
68406944 try leb.writeULEB128(writer, @as(u32, 1));
68416945
6842 var tag_val_payload: Value.Payload.U32 = .{
6843 .base = .{ .tag = .enum_field_index },
6844 .data = @intCast(u32, field_index),
6845 };
6846 const tag_value = try func.lowerConstant(Value.initPayload(&tag_val_payload.base), enum_ty);
6946 const tag_val = try mod.enumValueFieldIndex(enum_ty, field_index);
6947 const tag_value = try func.lowerConstant(tag_val, enum_ty);
68476948
68486949 switch (tag_value) {
68496950 .imm32 => |value| {
......@@ -6928,27 +7029,27 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
69287029 // finish function body
69297030 try writer.writeByte(std.wasm.opcode(.end));
69307031
6931 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
6932 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty}, slice_ty, func.target);
7032 const slice_ty = Type.slice_const_u8_sentinel_0;
7033 const func_type = try genFunctype(arena, .Unspecified, &.{int_tag_ty.ip_index}, slice_ty, mod);
69337034 return func.bin_file.createFunction(func_name, func_type, &body_list, &relocs);
69347035}
69357036
69367037fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7038 const mod = func.bin_file.base.options.module.?;
69377039 const ty_op = func.air.instructions.items(.data)[inst].ty_op;
69387040
69397041 const operand = try func.resolveInst(ty_op.operand);
69407042 const error_set_ty = func.air.getRefType(ty_op.ty);
69417043 const result = try func.allocLocal(Type.bool);
69427044
6943 const names = error_set_ty.errorSetNames();
7045 const names = error_set_ty.errorSetNames(mod);
69447046 var values = try std.ArrayList(u32).initCapacity(func.gpa, names.len);
69457047 defer values.deinit();
69467048
6947 const module = func.bin_file.base.options.module.?;
69487049 var lowest: ?u32 = null;
69497050 var highest: ?u32 = null;
69507051 for (names) |name| {
6951 const err_int = module.global_error_set.get(name).?;
7052 const err_int = @intCast(Module.ErrorInt, mod.global_error_set.getIndex(name).?);
69527053 if (lowest) |*l| {
69537054 if (err_int < l.*) {
69547055 l.* = err_int;
......@@ -7019,12 +7120,13 @@ inline fn useAtomicFeature(func: *const CodeGen) bool {
70197120}
70207121
70217122fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7123 const mod = func.bin_file.base.options.module.?;
70227124 const ty_pl = func.air.instructions.items(.data)[inst].ty_pl;
70237125 const extra = func.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
70247126
7025 const ptr_ty = func.air.typeOf(extra.ptr);
7026 const ty = ptr_ty.childType();
7027 const result_ty = func.air.typeOfIndex(inst);
7127 const ptr_ty = func.typeOf(extra.ptr);
7128 const ty = ptr_ty.childType(mod);
7129 const result_ty = func.typeOfIndex(inst);
70287130
70297131 const ptr_operand = try func.resolveInst(extra.ptr);
70307132 const expected_val = try func.resolveInst(extra.expected_value);
......@@ -7037,7 +7139,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70377139 try func.emitWValue(ptr_operand);
70387140 try func.lowerToStack(expected_val);
70397141 try func.lowerToStack(new_val);
7040 try func.addAtomicMemArg(switch (ty.abiSize(func.target)) {
7142 try func.addAtomicMemArg(switch (ty.abiSize(mod)) {
70417143 1 => .i32_atomic_rmw8_cmpxchg_u,
70427144 2 => .i32_atomic_rmw16_cmpxchg_u,
70437145 4 => .i32_atomic_rmw_cmpxchg,
......@@ -7045,14 +7147,14 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70457147 else => |size| return func.fail("TODO: implement `@cmpxchg` for types with abi size '{d}'", .{size}),
70467148 }, .{
70477149 .offset = ptr_operand.offset(),
7048 .alignment = ty.abiAlignment(func.target),
7150 .alignment = ty.abiAlignment(mod),
70497151 });
70507152 try func.addLabel(.local_tee, val_local.local.value);
70517153 _ = try func.cmp(.stack, expected_val, ty, .eq);
70527154 try func.addLabel(.local_set, cmp_result.local.value);
70537155 break :val val_local;
70547156 } else val: {
7055 if (ty.abiSize(func.target) > 8) {
7157 if (ty.abiSize(mod) > 8) {
70567158 return func.fail("TODO: Implement `@cmpxchg` for types larger than abi size of 8 bytes", .{});
70577159 }
70587160 const ptr_val = try WValue.toLocal(try func.load(ptr_operand, ty, 0), func, ty);
......@@ -7068,7 +7170,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70687170 break :val ptr_val;
70697171 };
70707172
7071 const result_ptr = if (isByRef(result_ty, func.target)) val: {
7173 const result_ptr = if (isByRef(result_ty, mod)) val: {
70727174 try func.emitWValue(cmp_result);
70737175 try func.addImm32(-1);
70747176 try func.addTag(.i32_xor);
......@@ -7076,7 +7178,7 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70767178 try func.addTag(.i32_and);
70777179 const and_result = try WValue.toLocal(.stack, func, Type.bool);
70787180 const result_ptr = try func.allocStack(result_ty);
7079 try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(func.target)));
7181 try func.store(result_ptr, and_result, Type.bool, @intCast(u32, ty.abiSize(mod)));
70807182 try func.store(result_ptr, ptr_val, ty, 0);
70817183 break :val result_ptr;
70827184 } else val: {
......@@ -7087,16 +7189,17 @@ fn airCmpxchg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
70877189 break :val try WValue.toLocal(.stack, func, result_ty);
70887190 };
70897191
7090 return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.new_value, extra.expected_value });
7192 return func.finishAir(inst, result_ptr, &.{ extra.ptr, extra.expected_value, extra.new_value });
70917193}
70927194
70937195fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7196 const mod = func.bin_file.base.options.module.?;
70947197 const atomic_load = func.air.instructions.items(.data)[inst].atomic_load;
70957198 const ptr = try func.resolveInst(atomic_load.ptr);
7096 const ty = func.air.typeOfIndex(inst);
7199 const ty = func.typeOfIndex(inst);
70977200
70987201 if (func.useAtomicFeature()) {
7099 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {
7202 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) {
71007203 1 => .i32_atomic_load8_u,
71017204 2 => .i32_atomic_load16_u,
71027205 4 => .i32_atomic_load,
......@@ -7106,7 +7209,7 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71067209 try func.emitWValue(ptr);
71077210 try func.addAtomicMemArg(tag, .{
71087211 .offset = ptr.offset(),
7109 .alignment = ty.abiAlignment(func.target),
7212 .alignment = ty.abiAlignment(mod),
71107213 });
71117214 } else {
71127215 _ = try func.load(ptr, ty, 0);
......@@ -7117,12 +7220,13 @@ fn airAtomicLoad(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71177220}
71187221
71197222fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7223 const mod = func.bin_file.base.options.module.?;
71207224 const pl_op = func.air.instructions.items(.data)[inst].pl_op;
71217225 const extra = func.air.extraData(Air.AtomicRmw, pl_op.payload).data;
71227226
71237227 const ptr = try func.resolveInst(pl_op.operand);
71247228 const operand = try func.resolveInst(extra.operand);
7125 const ty = func.air.typeOfIndex(inst);
7229 const ty = func.typeOfIndex(inst);
71267230 const op: std.builtin.AtomicRmwOp = extra.op();
71277231
71287232 if (func.useAtomicFeature()) {
......@@ -7140,7 +7244,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71407244 try func.emitWValue(ptr);
71417245 try func.emitWValue(value);
71427246 if (op == .Nand) {
7143 const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?;
7247 const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?;
71447248
71457249 const and_res = try func.binOp(value, operand, ty, .@"and");
71467250 if (wasm_bits == 32)
......@@ -7157,7 +7261,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71577261 try func.addTag(.select);
71587262 }
71597263 try func.addAtomicMemArg(
7160 switch (ty.abiSize(func.target)) {
7264 switch (ty.abiSize(mod)) {
71617265 1 => .i32_atomic_rmw8_cmpxchg_u,
71627266 2 => .i32_atomic_rmw16_cmpxchg_u,
71637267 4 => .i32_atomic_rmw_cmpxchg,
......@@ -7166,7 +7270,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71667270 },
71677271 .{
71687272 .offset = ptr.offset(),
7169 .alignment = ty.abiAlignment(func.target),
7273 .alignment = ty.abiAlignment(mod),
71707274 },
71717275 );
71727276 const select_res = try func.allocLocal(ty);
......@@ -7185,7 +7289,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
71857289 else => {
71867290 try func.emitWValue(ptr);
71877291 try func.emitWValue(operand);
7188 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {
7292 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) {
71897293 1 => switch (op) {
71907294 .Xchg => .i32_atomic_rmw8_xchg_u,
71917295 .Add => .i32_atomic_rmw8_add_u,
......@@ -7226,7 +7330,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
72267330 };
72277331 try func.addAtomicMemArg(tag, .{
72287332 .offset = ptr.offset(),
7229 .alignment = ty.abiAlignment(func.target),
7333 .alignment = ty.abiAlignment(mod),
72307334 });
72317335 const result = try WValue.toLocal(.stack, func, ty);
72327336 return func.finishAir(inst, result, &.{ pl_op.operand, extra.operand });
......@@ -7255,7 +7359,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
72557359 .Xor => .xor,
72567360 else => unreachable,
72577361 });
7258 if (ty.isInt() and (op == .Add or op == .Sub)) {
7362 if (ty.isInt(mod) and (op == .Add or op == .Sub)) {
72597363 _ = try func.wrapOperand(.stack, ty);
72607364 }
72617365 try func.store(.stack, .stack, ty, ptr.offset());
......@@ -7271,7 +7375,7 @@ fn airAtomicRmw(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
72717375 try func.store(.stack, .stack, ty, ptr.offset());
72727376 },
72737377 .Nand => {
7274 const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(func.target))).?;
7378 const wasm_bits = toWasmBits(@intCast(u16, ty.bitSize(mod))).?;
72757379
72767380 try func.emitWValue(ptr);
72777381 const and_res = try func.binOp(result, operand, ty, .@"and");
......@@ -7302,15 +7406,16 @@ fn airFence(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
73027406}
73037407
73047408fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
7409 const mod = func.bin_file.base.options.module.?;
73057410 const bin_op = func.air.instructions.items(.data)[inst].bin_op;
73067411
73077412 const ptr = try func.resolveInst(bin_op.lhs);
73087413 const operand = try func.resolveInst(bin_op.rhs);
7309 const ptr_ty = func.air.typeOf(bin_op.lhs);
7310 const ty = ptr_ty.childType();
7414 const ptr_ty = func.typeOf(bin_op.lhs);
7415 const ty = ptr_ty.childType(mod);
73117416
73127417 if (func.useAtomicFeature()) {
7313 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(func.target)) {
7418 const tag: wasm.AtomicsOpcode = switch (ty.abiSize(mod)) {
73147419 1 => .i32_atomic_store8,
73157420 2 => .i32_atomic_store16,
73167421 4 => .i32_atomic_store,
......@@ -7321,7 +7426,7 @@ fn airAtomicStore(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
73217426 try func.lowerToStack(operand);
73227427 try func.addAtomicMemArg(tag, .{
73237428 .offset = ptr.offset(),
7324 .alignment = ty.abiAlignment(func.target),
7429 .alignment = ty.abiAlignment(mod),
73257430 });
73267431 } else {
73277432 try func.store(ptr, operand, ty, 0);
......@@ -7338,3 +7443,13 @@ fn airFrameAddress(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
73387443 const result = try WValue.toLocal(.stack, func, Type.usize);
73397444 return func.finishAir(inst, result, &.{});
73407445}
7446
7447fn typeOf(func: *CodeGen, inst: Air.Inst.Ref) Type {
7448 const mod = func.bin_file.base.options.module.?;
7449 return func.air.typeOf(inst, &mod.intern_pool);
7450}
7451
7452fn typeOfIndex(func: *CodeGen, inst: Air.Inst.Index) Type {
7453 const mod = func.bin_file.base.options.module.?;
7454 return func.air.typeOfIndex(inst, &mod.intern_pool);
7455}
src/arch/wasm/Emit.zig+1-1
......@@ -254,7 +254,7 @@ fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
254254 @setCold(true);
255255 std.debug.assert(emit.error_msg == null);
256256 const mod = emit.bin_file.base.options.module.?;
257 emit.error_msg = try Module.ErrorMsg.create(emit.bin_file.base.allocator, mod.declPtr(emit.decl_index).srcLoc(), format, args);
257 emit.error_msg = try Module.ErrorMsg.create(emit.bin_file.base.allocator, mod.declPtr(emit.decl_index).srcLoc(mod), format, args);
258258 return error.EmitFail;
259259}
260260
src/arch/wasm/abi.zig+33-30
......@@ -5,9 +5,11 @@
55//! Note: Above mentioned document is not an official specification, therefore called a convention.
66
77const std = @import("std");
8const Type = @import("../../type.zig").Type;
98const Target = std.Target;
109
10const Type = @import("../../type.zig").Type;
11const Module = @import("../../Module.zig");
12
1113/// Defines how to pass a type as part of a function signature,
1214/// both for parameters as well as return values.
1315pub const Class = enum { direct, indirect, none };
......@@ -19,27 +21,28 @@ const direct: [2]Class = .{ .direct, .none };
1921/// Classifies a given Zig type to determine how they must be passed
2022/// or returned as value within a wasm function.
2123/// When all elements result in `.none`, no value must be passed in or returned.
22pub fn classifyType(ty: Type, target: Target) [2]Class {
23 if (!ty.hasRuntimeBitsIgnoreComptime()) return none;
24 switch (ty.zigTypeTag()) {
24pub fn classifyType(ty: Type, mod: *Module) [2]Class {
25 const target = mod.getTarget();
26 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none;
27 switch (ty.zigTypeTag(mod)) {
2528 .Struct => {
26 if (ty.containerLayout() == .Packed) {
27 if (ty.bitSize(target) <= 64) return direct;
29 if (ty.containerLayout(mod) == .Packed) {
30 if (ty.bitSize(mod) <= 64) return direct;
2831 return .{ .direct, .direct };
2932 }
3033 // When the struct type is non-scalar
31 if (ty.structFieldCount() > 1) return memory;
34 if (ty.structFieldCount(mod) > 1) return memory;
3235 // When the struct's alignment is non-natural
33 const field = ty.structFields().values()[0];
36 const field = ty.structFields(mod).values()[0];
3437 if (field.abi_align != 0) {
35 if (field.abi_align > field.ty.abiAlignment(target)) {
38 if (field.abi_align > field.ty.abiAlignment(mod)) {
3639 return memory;
3740 }
3841 }
39 return classifyType(field.ty, target);
42 return classifyType(field.ty, mod);
4043 },
4144 .Int, .Enum, .ErrorSet, .Vector => {
42 const int_bits = ty.intInfo(target).bits;
45 const int_bits = ty.intInfo(mod).bits;
4346 if (int_bits <= 64) return direct;
4447 if (int_bits <= 128) return .{ .direct, .direct };
4548 return memory;
......@@ -53,22 +56,22 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
5356 .Bool => return direct,
5457 .Array => return memory,
5558 .Optional => {
56 std.debug.assert(ty.isPtrLikeOptional());
59 std.debug.assert(ty.isPtrLikeOptional(mod));
5760 return direct;
5861 },
5962 .Pointer => {
60 std.debug.assert(!ty.isSlice());
63 std.debug.assert(!ty.isSlice(mod));
6164 return direct;
6265 },
6366 .Union => {
64 if (ty.containerLayout() == .Packed) {
65 if (ty.bitSize(target) <= 64) return direct;
67 if (ty.containerLayout(mod) == .Packed) {
68 if (ty.bitSize(mod) <= 64) return direct;
6669 return .{ .direct, .direct };
6770 }
68 const layout = ty.unionGetLayout(target);
71 const layout = ty.unionGetLayout(mod);
6972 std.debug.assert(layout.tag_size == 0);
70 if (ty.unionFields().count() > 1) return memory;
71 return classifyType(ty.unionFields().values()[0].ty, target);
73 if (ty.unionFields(mod).count() > 1) return memory;
74 return classifyType(ty.unionFields(mod).values()[0].ty, mod);
7275 },
7376 .ErrorUnion,
7477 .Frame,
......@@ -90,29 +93,29 @@ pub fn classifyType(ty: Type, target: Target) [2]Class {
9093/// Returns the scalar type a given type can represent.
9194/// Asserts given type can be represented as scalar, such as
9295/// a struct with a single scalar field.
93pub fn scalarType(ty: Type, target: std.Target) Type {
94 switch (ty.zigTypeTag()) {
96pub fn scalarType(ty: Type, mod: *Module) Type {
97 switch (ty.zigTypeTag(mod)) {
9598 .Struct => {
96 switch (ty.containerLayout()) {
99 switch (ty.containerLayout(mod)) {
97100 .Packed => {
98 const struct_obj = ty.castTag(.@"struct").?.data;
99 return scalarType(struct_obj.backing_int_ty, target);
101 const struct_obj = mod.typeToStruct(ty).?;
102 return scalarType(struct_obj.backing_int_ty, mod);
100103 },
101104 else => {
102 std.debug.assert(ty.structFieldCount() == 1);
103 return scalarType(ty.structFieldType(0), target);
105 std.debug.assert(ty.structFieldCount(mod) == 1);
106 return scalarType(ty.structFieldType(0, mod), mod);
104107 },
105108 }
106109 },
107110 .Union => {
108 if (ty.containerLayout() != .Packed) {
109 const layout = ty.unionGetLayout(target);
111 if (ty.containerLayout(mod) != .Packed) {
112 const layout = ty.unionGetLayout(mod);
110113 if (layout.payload_size == 0 and layout.tag_size != 0) {
111 return scalarType(ty.unionTagTypeSafety().?, target);
114 return scalarType(ty.unionTagTypeSafety(mod).?, mod);
112115 }
113 std.debug.assert(ty.unionFields().count() == 1);
116 std.debug.assert(ty.unionFields(mod).count() == 1);
114117 }
115 return scalarType(ty.unionFields().values()[0].ty, target);
118 return scalarType(ty.unionFields(mod).values()[0].ty, mod);
116119 },
117120 else => return ty,
118121 }
src/arch/x86_64/CodeGen.zig+784-772
......@@ -26,6 +26,7 @@ const Liveness = @import("../../Liveness.zig");
2626const Lower = @import("Lower.zig");
2727const Mir = @import("Mir.zig");
2828const Module = @import("../../Module.zig");
29const InternPool = @import("../../InternPool.zig");
2930const Target = std.Target;
3031const Type = @import("../../type.zig").Type;
3132const TypedValue = @import("../../TypedValue.zig");
......@@ -112,10 +113,10 @@ const Owner = union(enum) {
112113 mod_fn: *const Module.Fn,
113114 lazy_sym: link.File.LazySymbol,
114115
115 fn getDecl(owner: Owner) Module.Decl.Index {
116 fn getDecl(owner: Owner, mod: *Module) Module.Decl.Index {
116117 return switch (owner) {
117118 .mod_fn => |mod_fn| mod_fn.owner_decl,
118 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(),
119 .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(mod),
119120 };
120121 }
121122
......@@ -447,7 +448,7 @@ const InstTracking = struct {
447448 else => unreachable,
448449 }
449450 tracking_log.debug("spill %{d} from {} to {}", .{ inst, self.short, self.long });
450 try function.genCopy(function.air.typeOfIndex(inst), self.long, self.short);
451 try function.genCopy(function.typeOfIndex(inst), self.long, self.short);
451452 }
452453
453454 fn reuseFrame(self: *InstTracking) void {
......@@ -537,7 +538,7 @@ const InstTracking = struct {
537538 inst: Air.Inst.Index,
538539 target: InstTracking,
539540 ) !void {
540 const ty = function.air.typeOfIndex(inst);
541 const ty = function.typeOfIndex(inst);
541542 if ((self.long == .none or self.long == .reserved_frame) and target.long == .load_frame)
542543 try function.genCopy(ty, target.long, self.short);
543544 try function.genCopy(ty, target.short, self.short);
......@@ -605,14 +606,14 @@ const FrameAlloc = struct {
605606 .ref_count = 0,
606607 };
607608 }
608 fn initType(ty: Type, target: Target) FrameAlloc {
609 return init(.{ .size = ty.abiSize(target), .alignment = ty.abiAlignment(target) });
609 fn initType(ty: Type, mod: *Module) FrameAlloc {
610 return init(.{ .size = ty.abiSize(mod), .alignment = ty.abiAlignment(mod) });
610611 }
611612};
612613
613614const StackAllocation = struct {
614615 inst: ?Air.Inst.Index,
615 /// TODO do we need size? should be determined by inst.ty.abiSize(self.target.*)
616 /// TODO do we need size? should be determined by inst.ty.abiSize(mod)
616617 size: u32,
617618};
618619
......@@ -631,7 +632,7 @@ const Self = @This();
631632pub fn generate(
632633 bin_file: *link.File,
633634 src_loc: Module.SrcLoc,
634 module_fn: *Module.Fn,
635 module_fn_index: Module.Fn.Index,
635636 air: Air,
636637 liveness: Liveness,
637638 code: *std.ArrayList(u8),
......@@ -642,6 +643,7 @@ pub fn generate(
642643 }
643644
644645 const mod = bin_file.options.module.?;
646 const module_fn = mod.funcPtr(module_fn_index);
645647 const fn_owner_decl = mod.declPtr(module_fn.owner_decl);
646648 assert(fn_owner_decl.has_tv);
647649 const fn_type = fn_owner_decl.ty;
......@@ -686,7 +688,7 @@ pub fn generate(
686688 @enumToInt(FrameIndex.stack_frame),
687689 FrameAlloc.init(.{
688690 .size = 0,
689 .alignment = if (mod.align_stack_fns.get(module_fn)) |set_align_stack|
691 .alignment = if (mod.align_stack_fns.get(module_fn_index)) |set_align_stack|
690692 set_align_stack.alignment
691693 else
692694 1,
......@@ -697,7 +699,8 @@ pub fn generate(
697699 FrameAlloc.init(.{ .size = 0, .alignment = 1 }),
698700 );
699701
700 var call_info = function.resolveCallingConventionValues(fn_type, &.{}, .args_frame) catch |err| switch (err) {
702 const fn_info = mod.typeToFunc(fn_type).?;
703 var call_info = function.resolveCallingConventionValues(fn_info, &.{}, .args_frame) catch |err| switch (err) {
701704 error.CodegenFail => return Result{ .fail = function.err_msg.? },
702705 error.OutOfRegisters => return Result{
703706 .fail = try ErrorMsg.create(
......@@ -714,12 +717,12 @@ pub fn generate(
714717 function.args = call_info.args;
715718 function.ret_mcv = call_info.return_value;
716719 function.frame_allocs.set(@enumToInt(FrameIndex.ret_addr), FrameAlloc.init(.{
717 .size = Type.usize.abiSize(function.target.*),
718 .alignment = @min(Type.usize.abiAlignment(function.target.*), call_info.stack_align),
720 .size = Type.usize.abiSize(mod),
721 .alignment = @min(Type.usize.abiAlignment(mod), call_info.stack_align),
719722 }));
720723 function.frame_allocs.set(@enumToInt(FrameIndex.base_ptr), FrameAlloc.init(.{
721 .size = Type.usize.abiSize(function.target.*),
722 .alignment = @min(Type.usize.abiAlignment(function.target.*) * 2, call_info.stack_align),
724 .size = Type.usize.abiSize(mod),
725 .alignment = @min(Type.usize.abiAlignment(mod) * 2, call_info.stack_align),
723726 }));
724727 function.frame_allocs.set(
725728 @enumToInt(FrameIndex.args_frame),
......@@ -1565,7 +1568,8 @@ fn asmMemoryRegisterImmediate(
15651568}
15661569
15671570fn gen(self: *Self) InnerError!void {
1568 const cc = self.fn_type.fnCallingConvention();
1571 const mod = self.bin_file.options.module.?;
1572 const cc = self.fn_type.fnCallingConvention(mod);
15691573 if (cc != .Naked) {
15701574 try self.asmRegister(.{ ._, .push }, .rbp);
15711575 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
......@@ -1582,7 +1586,7 @@ fn gen(self: *Self) InnerError!void {
15821586 // register which the callee is free to clobber. Therefore, we purposely
15831587 // spill it to stack immediately.
15841588 const frame_index =
1585 try self.allocFrameIndex(FrameAlloc.initType(Type.usize, self.target.*));
1589 try self.allocFrameIndex(FrameAlloc.initType(Type.usize, mod));
15861590 try self.genSetMem(
15871591 .{ .frame = frame_index },
15881592 0,
......@@ -1724,6 +1728,8 @@ fn gen(self: *Self) InnerError!void {
17241728}
17251729
17261730fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
1731 const mod = self.bin_file.options.module.?;
1732 const ip = &mod.intern_pool;
17271733 const air_tags = self.air.instructions.items(.tag);
17281734
17291735 for (body) |inst| {
......@@ -1732,7 +1738,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
17321738 try self.mir_to_air_map.put(self.gpa, mir_inst, inst);
17331739 }
17341740
1735 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) continue;
1741 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip)) continue;
17361742 wip_mir_log.debug("{}", .{self.fmtAir(inst)});
17371743 verbose_tracking_log.debug("{}", .{self.fmtTracking()});
17381744
......@@ -1916,8 +1922,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
19161922 .ptr_elem_val => try self.airPtrElemVal(inst),
19171923 .ptr_elem_ptr => try self.airPtrElemPtr(inst),
19181924
1919 .constant => unreachable, // excluded from function bodies
1920 .const_ty => unreachable, // excluded from function bodies
1925 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
19211926 .unreach => if (self.wantSafety()) try self.airTrap() else self.finishAirBookkeeping(),
19221927
19231928 .optional_payload => try self.airOptionalPayload(inst),
......@@ -1999,7 +2004,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
19992004}
20002005
20012006fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
2002 switch (lazy_sym.ty.zigTypeTag()) {
2007 const mod = self.bin_file.options.module.?;
2008 switch (lazy_sym.ty.zigTypeTag(mod)) {
20032009 .Enum => {
20042010 const enum_ty = lazy_sym.ty;
20052011 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(self.bin_file.options.module.?)});
......@@ -2011,7 +2017,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
20112017 const ret_reg = param_regs[0];
20122018 const enum_mcv = MCValue{ .register = param_regs[1] };
20132019
2014 var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount());
2020 var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount(mod));
20152021 defer self.gpa.free(exitlude_jump_relocs);
20162022
20172023 const data_reg = try self.register_manager.allocReg(null, gp);
......@@ -2020,16 +2026,10 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
20202026 try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
20212027
20222028 var data_off: i32 = 0;
2023 for (
2024 exitlude_jump_relocs,
2025 enum_ty.enumFields().keys(),
2026 0..,
2027 ) |*exitlude_jump_reloc, tag_name, index| {
2028 var tag_pl = Value.Payload.U32{
2029 .base = .{ .tag = .enum_field_index },
2030 .data = @intCast(u32, index),
2031 };
2032 const tag_val = Value.initPayload(&tag_pl.base);
2029 for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, index_usize| {
2030 const index = @intCast(u32, index_usize);
2031 const tag_name = mod.intern_pool.stringToSlice(enum_ty.enumFields(mod)[index_usize]);
2032 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
20332033 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
20342034 try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv);
20352035 const skip_reloc = try self.asmJccReloc(undefined, .ne);
......@@ -2092,10 +2092,8 @@ fn feed(self: *Self, bt: *Liveness.BigTomb, operand: Air.Inst.Ref) void {
20922092
20932093/// Asserts there is already capacity to insert into top branch inst_table.
20942094fn processDeath(self: *Self, inst: Air.Inst.Index) void {
2095 switch (self.air.instructions.items(.tag)[inst]) {
2096 .constant, .const_ty => unreachable,
2097 else => self.inst_tracking.getPtr(inst).?.die(self, inst),
2098 }
2095 assert(self.air.instructions.items(.tag)[inst] != .interned);
2096 self.inst_tracking.getPtr(inst).?.die(self, inst);
20992097}
21002098
21012099/// Called when there are no operands, and the instruction is always unreferenced.
......@@ -2126,10 +2124,7 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
21262124 const dies = @truncate(u1, tomb_bits) != 0;
21272125 tomb_bits >>= 1;
21282126 if (!dies) continue;
2129 const op_int = @enumToInt(op);
2130 if (op_int < Air.Inst.Ref.typed_value_map.len) continue;
2131 const op_index = @intCast(Air.Inst.Index, op_int - Air.Inst.Ref.typed_value_map.len);
2132 self.processDeath(op_index);
2127 self.processDeath(Air.refToIndexAllowNone(op) orelse continue);
21332128 }
21342129 self.finishAirResult(inst, result);
21352130}
......@@ -2252,19 +2247,19 @@ fn allocFrameIndex(self: *Self, alloc: FrameAlloc) !FrameIndex {
22522247
22532248/// Use a pointer instruction as the basis for allocating stack memory.
22542249fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !FrameIndex {
2255 const ptr_ty = self.air.typeOfIndex(inst);
2256 const val_ty = ptr_ty.childType();
2250 const mod = self.bin_file.options.module.?;
2251 const ptr_ty = self.typeOfIndex(inst);
2252 const val_ty = ptr_ty.childType(mod);
22572253 return self.allocFrameIndex(FrameAlloc.init(.{
2258 .size = math.cast(u32, val_ty.abiSize(self.target.*)) orelse {
2259 const mod = self.bin_file.options.module.?;
2254 .size = math.cast(u32, val_ty.abiSize(mod)) orelse {
22602255 return self.fail("type '{}' too big to fit into stack frame", .{val_ty.fmt(mod)});
22612256 },
2262 .alignment = @max(ptr_ty.ptrAlignment(self.target.*), 1),
2257 .alignment = @max(ptr_ty.ptrAlignment(mod), 1),
22632258 }));
22642259}
22652260
22662261fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
2267 return self.allocRegOrMemAdvanced(self.air.typeOfIndex(inst), inst, reg_ok);
2262 return self.allocRegOrMemAdvanced(self.typeOfIndex(inst), inst, reg_ok);
22682263}
22692264
22702265fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue {
......@@ -2272,20 +2267,20 @@ fn allocTempRegOrMem(self: *Self, elem_ty: Type, reg_ok: bool) !MCValue {
22722267}
22732268
22742269fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: bool) !MCValue {
2275 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) orelse {
2276 const mod = self.bin_file.options.module.?;
2270 const mod = self.bin_file.options.module.?;
2271 const abi_size = math.cast(u32, ty.abiSize(mod)) orelse {
22772272 return self.fail("type '{}' too big to fit into stack frame", .{ty.fmt(mod)});
22782273 };
22792274
22802275 if (reg_ok) need_mem: {
2281 if (abi_size <= @as(u32, switch (ty.zigTypeTag()) {
2276 if (abi_size <= @as(u32, switch (ty.zigTypeTag(mod)) {
22822277 .Float => switch (ty.floatBits(self.target.*)) {
22832278 16, 32, 64, 128 => 16,
22842279 80 => break :need_mem,
22852280 else => unreachable,
22862281 },
2287 .Vector => switch (ty.childType().zigTypeTag()) {
2288 .Float => switch (ty.childType().floatBits(self.target.*)) {
2282 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
2283 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
22892284 16, 32, 64, 128 => if (self.hasFeature(.avx)) 32 else 16,
22902285 80 => break :need_mem,
22912286 else => unreachable,
......@@ -2294,18 +2289,18 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b
22942289 },
22952290 else => 8,
22962291 })) {
2297 if (self.register_manager.tryAllocReg(inst, regClassForType(ty))) |reg| {
2292 if (self.register_manager.tryAllocReg(inst, regClassForType(ty, mod))) |reg| {
22982293 return MCValue{ .register = registerAlias(reg, abi_size) };
22992294 }
23002295 }
23012296 }
23022297
2303 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, self.target.*));
2298 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ty, mod));
23042299 return .{ .load_frame = .{ .index = frame_index } };
23052300}
23062301
2307fn regClassForType(ty: Type) RegisterManager.RegisterBitSet {
2308 return switch (ty.zigTypeTag()) {
2302fn regClassForType(ty: Type, mod: *Module) RegisterManager.RegisterBitSet {
2303 return switch (ty.zigTypeTag(mod)) {
23092304 .Float, .Vector => sse,
23102305 else => gp,
23112306 };
......@@ -2449,7 +2444,8 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void {
24492444/// allocated. A second call to `copyToTmpRegister` may return the same register.
24502445/// This can have a side effect of spilling instructions to the stack to free up a register.
24512446fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
2452 const reg = try self.register_manager.allocReg(null, regClassForType(ty));
2447 const mod = self.bin_file.options.module.?;
2448 const reg = try self.register_manager.allocReg(null, regClassForType(ty, mod));
24532449 try self.genSetReg(reg, ty, mcv);
24542450 return reg;
24552451}
......@@ -2464,7 +2460,8 @@ fn copyToRegisterWithInstTracking(
24642460 ty: Type,
24652461 mcv: MCValue,
24662462) !MCValue {
2467 const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty));
2463 const mod = self.bin_file.options.module.?;
2464 const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty, mod));
24682465 try self.genSetReg(reg, ty, mcv);
24692466 return MCValue{ .register = reg };
24702467}
......@@ -2481,7 +2478,7 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
24812478 .load_frame => .{ .register_offset = .{
24822479 .reg = (try self.copyToRegisterWithInstTracking(
24832480 inst,
2484 self.air.typeOfIndex(inst),
2481 self.typeOfIndex(inst),
24852482 self.ret_mcv.long,
24862483 )).register,
24872484 .off = self.ret_mcv.short.indirect.off,
......@@ -2492,9 +2489,9 @@ fn airRetPtr(self: *Self, inst: Air.Inst.Index) !void {
24922489
24932490fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
24942491 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2495 const dst_ty = self.air.typeOfIndex(inst);
2492 const dst_ty = self.typeOfIndex(inst);
24962493 const dst_bits = dst_ty.floatBits(self.target.*);
2497 const src_ty = self.air.typeOf(ty_op.operand);
2494 const src_ty = self.typeOf(ty_op.operand);
24982495 const src_bits = src_ty.floatBits(self.target.*);
24992496
25002497 const src_mcv = try self.resolveInst(ty_op.operand);
......@@ -2558,9 +2555,9 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
25582555
25592556fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
25602557 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2561 const dst_ty = self.air.typeOfIndex(inst);
2558 const dst_ty = self.typeOfIndex(inst);
25622559 const dst_bits = dst_ty.floatBits(self.target.*);
2563 const src_ty = self.air.typeOf(ty_op.operand);
2560 const src_ty = self.typeOf(ty_op.operand);
25642561 const src_bits = src_ty.floatBits(self.target.*);
25652562
25662563 const src_mcv = try self.resolveInst(ty_op.operand);
......@@ -2618,14 +2615,15 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
26182615}
26192616
26202617fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
2618 const mod = self.bin_file.options.module.?;
26212619 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
26222620 const result: MCValue = result: {
2623 const src_ty = self.air.typeOf(ty_op.operand);
2624 const src_int_info = src_ty.intInfo(self.target.*);
2621 const src_ty = self.typeOf(ty_op.operand);
2622 const src_int_info = src_ty.intInfo(mod);
26252623
2626 const dst_ty = self.air.typeOfIndex(inst);
2627 const dst_int_info = dst_ty.intInfo(self.target.*);
2628 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
2624 const dst_ty = self.typeOfIndex(inst);
2625 const dst_int_info = dst_ty.intInfo(mod);
2626 const abi_size = @intCast(u32, dst_ty.abiSize(mod));
26292627
26302628 const min_ty = if (dst_int_info.bits < src_int_info.bits) dst_ty else src_ty;
26312629 const extend = switch (src_int_info.signedness) {
......@@ -2670,14 +2668,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
26702668
26712669 const high_bits = src_int_info.bits % 64;
26722670 if (high_bits > 0) {
2673 var high_pl = Type.Payload.Bits{
2674 .base = .{ .tag = switch (extend) {
2675 .signed => .int_signed,
2676 .unsigned => .int_unsigned,
2677 } },
2678 .data = high_bits,
2679 };
2680 const high_ty = Type.initPayload(&high_pl.base);
2671 const high_ty = try mod.intType(extend, high_bits);
26812672 try self.truncateRegister(high_ty, high_reg);
26822673 try self.genCopy(Type.usize, high_mcv, .{ .register = high_reg });
26832674 }
......@@ -2706,12 +2697,13 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
27062697}
27072698
27082699fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
2700 const mod = self.bin_file.options.module.?;
27092701 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
27102702
2711 const dst_ty = self.air.typeOfIndex(inst);
2712 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
2713 const src_ty = self.air.typeOf(ty_op.operand);
2714 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
2703 const dst_ty = self.typeOfIndex(inst);
2704 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
2705 const src_ty = self.typeOf(ty_op.operand);
2706 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
27152707
27162708 const result = result: {
27172709 const src_mcv = try self.resolveInst(ty_op.operand);
......@@ -2724,13 +2716,13 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
27242716 else
27252717 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
27262718
2727 if (dst_ty.zigTypeTag() == .Vector) {
2728 assert(src_ty.zigTypeTag() == .Vector and dst_ty.vectorLen() == src_ty.vectorLen());
2729 const dst_info = dst_ty.childType().intInfo(self.target.*);
2730 const src_info = src_ty.childType().intInfo(self.target.*);
2719 if (dst_ty.zigTypeTag(mod) == .Vector) {
2720 assert(src_ty.zigTypeTag(mod) == .Vector and dst_ty.vectorLen(mod) == src_ty.vectorLen(mod));
2721 const dst_info = dst_ty.childType(mod).intInfo(mod);
2722 const src_info = src_ty.childType(mod).intInfo(mod);
27312723 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_info.bits) {
27322724 8 => switch (src_info.bits) {
2733 16 => switch (dst_ty.vectorLen()) {
2725 16 => switch (dst_ty.vectorLen(mod)) {
27342726 1...8 => if (self.hasFeature(.avx)) .{ .vp_b, .ackusw } else .{ .p_b, .ackusw },
27352727 9...16 => if (self.hasFeature(.avx2)) .{ .vp_b, .ackusw } else null,
27362728 else => null,
......@@ -2738,7 +2730,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
27382730 else => null,
27392731 },
27402732 16 => switch (src_info.bits) {
2741 32 => switch (dst_ty.vectorLen()) {
2733 32 => switch (dst_ty.vectorLen(mod)) {
27422734 1...4 => if (self.hasFeature(.avx))
27432735 .{ .vp_w, .ackusd }
27442736 else if (self.hasFeature(.sse4_1))
......@@ -2755,29 +2747,21 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
27552747 dst_ty.fmt(self.bin_file.options.module.?),
27562748 });
27572749
2758 var mask_pl = Value.Payload.U64{
2759 .base = .{ .tag = .int_u64 },
2760 .data = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - dst_info.bits),
2761 };
2762 const mask_val = Value.initPayload(&mask_pl.base);
2750 const elem_ty = src_ty.childType(mod);
2751 const mask_val = try mod.intValue(elem_ty, @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - dst_info.bits));
27632752
2764 var splat_pl = Value.Payload.SubValue{
2765 .base = .{ .tag = .repeated },
2766 .data = mask_val,
2767 };
2768 const splat_val = Value.initPayload(&splat_pl.base);
2753 const splat_ty = try mod.vectorType(.{
2754 .len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
2755 .child = elem_ty.ip_index,
2756 });
2757 const splat_abi_size = @intCast(u32, splat_ty.abiSize(mod));
27692758
2770 var full_pl = Type.Payload.Array{
2771 .base = .{ .tag = .vector },
2772 .data = .{
2773 .len = @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits),
2774 .elem_type = src_ty.childType(),
2775 },
2776 };
2777 const full_ty = Type.initPayload(&full_pl.base);
2778 const full_abi_size = @intCast(u32, full_ty.abiSize(self.target.*));
2759 const splat_val = try mod.intern(.{ .aggregate = .{
2760 .ty = splat_ty.ip_index,
2761 .storage = .{ .repeated_elem = mask_val.ip_index },
2762 } });
27792763
2780 const splat_mcv = try self.genTypedValue(.{ .ty = full_ty, .val = splat_val });
2764 const splat_mcv = try self.genTypedValue(.{ .ty = splat_ty, .val = splat_val.toValue() });
27812765 const splat_addr_mcv: MCValue = switch (splat_mcv) {
27822766 .memory, .indirect, .load_frame => splat_mcv.address(),
27832767 else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) },
......@@ -2789,14 +2773,14 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
27892773 .{ .vp_, .@"and" },
27902774 dst_reg,
27912775 dst_reg,
2792 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(full_abi_size)),
2776 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(splat_abi_size)),
27932777 );
27942778 try self.asmRegisterRegisterRegister(mir_tag, dst_reg, dst_reg, dst_reg);
27952779 } else {
27962780 try self.asmRegisterMemory(
27972781 .{ .p_, .@"and" },
27982782 dst_reg,
2799 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(full_abi_size)),
2783 splat_addr_mcv.deref().mem(Memory.PtrSize.fromSize(splat_abi_size)),
28002784 );
28012785 try self.asmRegisterRegister(mir_tag, dst_reg, dst_reg);
28022786 }
......@@ -2819,7 +2803,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
28192803
28202804fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
28212805 const un_op = self.air.instructions.items(.data)[inst].un_op;
2822 const ty = self.air.typeOfIndex(inst);
2806 const ty = self.typeOfIndex(inst);
28232807
28242808 const operand = try self.resolveInst(un_op);
28252809 const dst_mcv = if (self.reuseOperand(inst, un_op, 0, operand))
......@@ -2831,20 +2815,21 @@ fn airBoolToInt(self: *Self, inst: Air.Inst.Index) !void {
28312815}
28322816
28332817fn airSlice(self: *Self, inst: Air.Inst.Index) !void {
2818 const mod = self.bin_file.options.module.?;
28342819 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
28352820 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
28362821
2837 const slice_ty = self.air.typeOfIndex(inst);
2822 const slice_ty = self.typeOfIndex(inst);
28382823 const ptr = try self.resolveInst(bin_op.lhs);
2839 const ptr_ty = self.air.typeOf(bin_op.lhs);
2824 const ptr_ty = self.typeOf(bin_op.lhs);
28402825 const len = try self.resolveInst(bin_op.rhs);
2841 const len_ty = self.air.typeOf(bin_op.rhs);
2826 const len_ty = self.typeOf(bin_op.rhs);
28422827
2843 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, self.target.*));
2828 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod));
28442829 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
28452830 try self.genSetMem(
28462831 .{ .frame = frame_index },
2847 @intCast(i32, ptr_ty.abiSize(self.target.*)),
2832 @intCast(i32, ptr_ty.abiSize(mod)),
28482833 len_ty,
28492834 len,
28502835 );
......@@ -2873,23 +2858,24 @@ fn airPtrArithmetic(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void
28732858}
28742859
28752860fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
2861 const mod = self.bin_file.options.module.?;
28762862 const air_tag = self.air.instructions.items(.tag);
28772863 const air_data = self.air.instructions.items(.data);
28782864
2879 const dst_ty = self.air.typeOf(dst_air);
2880 const dst_info = dst_ty.intInfo(self.target.*);
2865 const dst_ty = self.typeOf(dst_air);
2866 const dst_info = dst_ty.intInfo(mod);
28812867 if (Air.refToIndex(dst_air)) |inst| {
28822868 switch (air_tag[inst]) {
2883 .constant => {
2884 const src_val = self.air.values[air_data[inst].ty_pl.payload];
2869 .interned => {
2870 const src_val = air_data[inst].interned.toValue();
28852871 var space: Value.BigIntSpace = undefined;
2886 const src_int = src_val.toBigInt(&space, self.target.*);
2872 const src_int = src_val.toBigInt(&space, mod);
28872873 return @intCast(u16, src_int.bitCountTwosComp()) +
28882874 @boolToInt(src_int.positive and dst_info.signedness == .signed);
28892875 },
28902876 .intcast => {
2891 const src_ty = self.air.typeOf(air_data[inst].ty_op.operand);
2892 const src_info = src_ty.intInfo(self.target.*);
2877 const src_ty = self.typeOf(air_data[inst].ty_op.operand);
2878 const src_info = src_ty.intInfo(mod);
28932879 return @min(switch (src_info.signedness) {
28942880 .signed => switch (dst_info.signedness) {
28952881 .signed => src_info.bits,
......@@ -2908,20 +2894,18 @@ fn activeIntBits(self: *Self, dst_air: Air.Inst.Ref) u16 {
29082894}
29092895
29102896fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
2897 const mod = self.bin_file.options.module.?;
29112898 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
29122899 const result = result: {
29132900 const tag = self.air.instructions.items(.tag)[inst];
2914 const dst_ty = self.air.typeOfIndex(inst);
2915 switch (dst_ty.zigTypeTag()) {
2901 const dst_ty = self.typeOfIndex(inst);
2902 switch (dst_ty.zigTypeTag(mod)) {
29162903 .Float, .Vector => break :result try self.genBinOp(inst, tag, bin_op.lhs, bin_op.rhs),
29172904 else => {},
29182905 }
29192906
2920 const dst_info = dst_ty.intInfo(self.target.*);
2921 var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) {
2922 .signed => .int_signed,
2923 .unsigned => .int_unsigned,
2924 } }, .data = switch (tag) {
2907 const dst_info = dst_ty.intInfo(mod);
2908 const src_ty = try mod.intType(dst_info.signedness, switch (tag) {
29252909 else => unreachable,
29262910 .mul, .mulwrap => math.max3(
29272911 self.activeIntBits(bin_op.lhs),
......@@ -2929,8 +2913,7 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
29292913 dst_info.bits / 2,
29302914 ),
29312915 .div_trunc, .div_floor, .div_exact, .rem, .mod => dst_info.bits,
2932 } };
2933 const src_ty = Type.initPayload(&src_pl.base);
2916 });
29342917
29352918 try self.spillEflagsIfOccupied();
29362919 try self.spillRegisters(&.{ .rax, .rdx });
......@@ -2942,8 +2925,9 @@ fn airMulDivBinOp(self: *Self, inst: Air.Inst.Index) !void {
29422925}
29432926
29442927fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
2928 const mod = self.bin_file.options.module.?;
29452929 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2946 const ty = self.air.typeOf(bin_op.lhs);
2930 const ty = self.typeOf(bin_op.lhs);
29472931
29482932 const lhs_mcv = try self.resolveInst(bin_op.lhs);
29492933 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
......@@ -2968,7 +2952,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
29682952
29692953 const reg_bits = self.regBitSize(ty);
29702954 const reg_extra_bits = self.regExtraBits(ty);
2971 const cc: Condition = if (ty.isSignedInt()) cc: {
2955 const cc: Condition = if (ty.isSignedInt(mod)) cc: {
29722956 if (reg_extra_bits > 0) {
29732957 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
29742958 }
......@@ -2994,7 +2978,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
29942978 break :cc .o;
29952979 } else cc: {
29962980 try self.genSetReg(limit_reg, ty, .{
2997 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - ty.bitSize(self.target.*)),
2981 .immediate = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - ty.bitSize(mod)),
29982982 });
29992983
30002984 try self.genBinOpMir(.{ ._, .add }, ty, dst_mcv, rhs_mcv);
......@@ -3005,14 +2989,14 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
30052989 break :cc .c;
30062990 };
30072991
3008 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
2992 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(mod)), 2);
30092993 try self.asmCmovccRegisterRegister(
30102994 registerAlias(dst_reg, cmov_abi_size),
30112995 registerAlias(limit_reg, cmov_abi_size),
30122996 cc,
30132997 );
30142998
3015 if (reg_extra_bits > 0 and ty.isSignedInt()) {
2999 if (reg_extra_bits > 0 and ty.isSignedInt(mod)) {
30163000 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
30173001 }
30183002
......@@ -3020,8 +3004,9 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void {
30203004}
30213005
30223006fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
3007 const mod = self.bin_file.options.module.?;
30233008 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3024 const ty = self.air.typeOf(bin_op.lhs);
3009 const ty = self.typeOf(bin_op.lhs);
30253010
30263011 const lhs_mcv = try self.resolveInst(bin_op.lhs);
30273012 const dst_mcv = if (lhs_mcv.isRegister() and self.reuseOperand(inst, bin_op.lhs, 0, lhs_mcv))
......@@ -3046,7 +3031,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
30463031
30473032 const reg_bits = self.regBitSize(ty);
30483033 const reg_extra_bits = self.regExtraBits(ty);
3049 const cc: Condition = if (ty.isSignedInt()) cc: {
3034 const cc: Condition = if (ty.isSignedInt(mod)) cc: {
30503035 if (reg_extra_bits > 0) {
30513036 try self.genShiftBinOpMir(.{ ._l, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
30523037 }
......@@ -3076,14 +3061,14 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
30763061 break :cc .c;
30773062 };
30783063
3079 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
3064 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(mod)), 2);
30803065 try self.asmCmovccRegisterRegister(
30813066 registerAlias(dst_reg, cmov_abi_size),
30823067 registerAlias(limit_reg, cmov_abi_size),
30833068 cc,
30843069 );
30853070
3086 if (reg_extra_bits > 0 and ty.isSignedInt()) {
3071 if (reg_extra_bits > 0 and ty.isSignedInt(mod)) {
30873072 try self.genShiftBinOpMir(.{ ._r, .sa }, ty, dst_mcv, .{ .immediate = reg_extra_bits });
30883073 }
30893074
......@@ -3091,8 +3076,9 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void {
30913076}
30923077
30933078fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
3079 const mod = self.bin_file.options.module.?;
30943080 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
3095 const ty = self.air.typeOf(bin_op.lhs);
3081 const ty = self.typeOf(bin_op.lhs);
30963082
30973083 try self.spillRegisters(&.{ .rax, .rdx });
30983084 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
......@@ -3118,7 +3104,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
31183104 defer self.register_manager.unlockReg(limit_lock);
31193105
31203106 const reg_bits = self.regBitSize(ty);
3121 const cc: Condition = if (ty.isSignedInt()) cc: {
3107 const cc: Condition = if (ty.isSignedInt(mod)) cc: {
31223108 try self.genSetReg(limit_reg, ty, lhs_mcv);
31233109 try self.genBinOpMir(.{ ._, .xor }, ty, limit_mcv, rhs_mcv);
31243110 try self.genShiftBinOpMir(.{ ._, .sa }, ty, limit_mcv, .{ .immediate = reg_bits - 1 });
......@@ -3134,7 +3120,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
31343120 };
31353121
31363122 const dst_mcv = try self.genMulDivBinOp(.mul, inst, ty, ty, lhs_mcv, rhs_mcv);
3137 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(self.target.*)), 2);
3123 const cmov_abi_size = @max(@intCast(u32, ty.abiSize(mod)), 2);
31383124 try self.asmCmovccRegisterRegister(
31393125 registerAlias(dst_mcv.register, cmov_abi_size),
31403126 registerAlias(limit_reg, cmov_abi_size),
......@@ -3145,12 +3131,13 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void {
31453131}
31463132
31473133fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3134 const mod = self.bin_file.options.module.?;
31483135 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
31493136 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
31503137 const result: MCValue = result: {
31513138 const tag = self.air.instructions.items(.tag)[inst];
3152 const ty = self.air.typeOf(bin_op.lhs);
3153 switch (ty.zigTypeTag()) {
3139 const ty = self.typeOf(bin_op.lhs);
3140 switch (ty.zigTypeTag(mod)) {
31543141 .Vector => return self.fail("TODO implement add/sub with overflow for Vector type", .{}),
31553142 .Int => {
31563143 try self.spillEflagsIfOccupied();
......@@ -3160,13 +3147,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
31603147 .sub_with_overflow => .sub,
31613148 else => unreachable,
31623149 }, bin_op.lhs, bin_op.rhs);
3163 const int_info = ty.intInfo(self.target.*);
3150 const int_info = ty.intInfo(mod);
31643151 const cc: Condition = switch (int_info.signedness) {
31653152 .unsigned => .c,
31663153 .signed => .o,
31673154 };
31683155
3169 const tuple_ty = self.air.typeOfIndex(inst);
3156 const tuple_ty = self.typeOfIndex(inst);
31703157 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
31713158 switch (partial_mcv) {
31723159 .register => |reg| {
......@@ -3177,16 +3164,16 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
31773164 }
31783165
31793166 const frame_index =
3180 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));
3167 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
31813168 try self.genSetMem(
31823169 .{ .frame = frame_index },
3183 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),
3170 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
31843171 Type.u1,
31853172 .{ .eflags = cc },
31863173 );
31873174 try self.genSetMem(
31883175 .{ .frame = frame_index },
3189 @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)),
3176 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
31903177 ty,
31913178 partial_mcv,
31923179 );
......@@ -3194,7 +3181,7 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
31943181 }
31953182
31963183 const frame_index =
3197 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));
3184 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
31983185 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
31993186 break :result .{ .load_frame = .{ .index = frame_index } };
32003187 },
......@@ -3205,12 +3192,13 @@ fn airAddSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
32053192}
32063193
32073194fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3195 const mod = self.bin_file.options.module.?;
32083196 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
32093197 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
32103198 const result: MCValue = result: {
3211 const lhs_ty = self.air.typeOf(bin_op.lhs);
3212 const rhs_ty = self.air.typeOf(bin_op.rhs);
3213 switch (lhs_ty.zigTypeTag()) {
3199 const lhs_ty = self.typeOf(bin_op.lhs);
3200 const rhs_ty = self.typeOf(bin_op.rhs);
3201 switch (lhs_ty.zigTypeTag(mod)) {
32143202 .Vector => return self.fail("TODO implement shl with overflow for Vector type", .{}),
32153203 .Int => {
32163204 try self.spillEflagsIfOccupied();
......@@ -3219,7 +3207,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
32193207 const lhs = try self.resolveInst(bin_op.lhs);
32203208 const rhs = try self.resolveInst(bin_op.rhs);
32213209
3222 const int_info = lhs_ty.intInfo(self.target.*);
3210 const int_info = lhs_ty.intInfo(mod);
32233211
32243212 const partial_mcv = try self.genShiftBinOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);
32253213 const partial_lock = switch (partial_mcv) {
......@@ -3238,7 +3226,7 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
32383226 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, tmp_mcv, lhs);
32393227 const cc = Condition.ne;
32403228
3241 const tuple_ty = self.air.typeOfIndex(inst);
3229 const tuple_ty = self.typeOfIndex(inst);
32423230 if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) {
32433231 switch (partial_mcv) {
32443232 .register => |reg| {
......@@ -3249,24 +3237,24 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
32493237 }
32503238
32513239 const frame_index =
3252 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));
3240 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
32533241 try self.genSetMem(
32543242 .{ .frame = frame_index },
3255 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),
3256 tuple_ty.structFieldType(1),
3243 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3244 tuple_ty.structFieldType(1, mod),
32573245 .{ .eflags = cc },
32583246 );
32593247 try self.genSetMem(
32603248 .{ .frame = frame_index },
3261 @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)),
3262 tuple_ty.structFieldType(0),
3249 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3250 tuple_ty.structFieldType(0, mod),
32633251 partial_mcv,
32643252 );
32653253 break :result .{ .load_frame = .{ .index = frame_index } };
32663254 }
32673255
32683256 const frame_index =
3269 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));
3257 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
32703258 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
32713259 break :result .{ .load_frame = .{ .index = frame_index } };
32723260 },
......@@ -3283,29 +3271,20 @@ fn genSetFrameTruncatedOverflowCompare(
32833271 src_mcv: MCValue,
32843272 overflow_cc: ?Condition,
32853273) !void {
3274 const mod = self.bin_file.options.module.?;
32863275 const src_lock = switch (src_mcv) {
32873276 .register => |reg| self.register_manager.lockReg(reg),
32883277 else => null,
32893278 };
32903279 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
32913280
3292 const ty = tuple_ty.structFieldType(0);
3293 const int_info = ty.intInfo(self.target.*);
3281 const ty = tuple_ty.structFieldType(0, mod);
3282 const int_info = ty.intInfo(mod);
32943283
3295 var hi_limb_pl = Type.Payload.Bits{
3296 .base = .{ .tag = switch (int_info.signedness) {
3297 .signed => .int_signed,
3298 .unsigned => .int_unsigned,
3299 } },
3300 .data = (int_info.bits - 1) % 64 + 1,
3301 };
3302 const hi_limb_ty = Type.initPayload(&hi_limb_pl.base);
3284 const hi_limb_bits = (int_info.bits - 1) % 64 + 1;
3285 const hi_limb_ty = try mod.intType(int_info.signedness, hi_limb_bits);
33033286
3304 var rest_pl = Type.Payload.Bits{
3305 .base = .{ .tag = .int_unsigned },
3306 .data = int_info.bits - hi_limb_pl.data,
3307 };
3308 const rest_ty = Type.initPayload(&rest_pl.base);
3287 const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_bits);
33093288
33103289 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp);
33113290 const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
......@@ -3335,7 +3314,7 @@ fn genSetFrameTruncatedOverflowCompare(
33353314 );
33363315 }
33373316
3338 const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*));
3317 const payload_off = @intCast(i32, tuple_ty.structFieldOffset(0, mod));
33393318 if (hi_limb_off > 0) try self.genSetMem(.{ .frame = frame_index }, payload_off, rest_ty, src_mcv);
33403319 try self.genSetMem(
33413320 .{ .frame = frame_index },
......@@ -3345,23 +3324,24 @@ fn genSetFrameTruncatedOverflowCompare(
33453324 );
33463325 try self.genSetMem(
33473326 .{ .frame = frame_index },
3348 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),
3349 tuple_ty.structFieldType(1),
3327 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3328 tuple_ty.structFieldType(1, mod),
33503329 if (overflow_cc) |_| .{ .register = overflow_reg.to8() } else .{ .eflags = .ne },
33513330 );
33523331}
33533332
33543333fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
3334 const mod = self.bin_file.options.module.?;
33553335 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
33563336 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
3357 const dst_ty = self.air.typeOf(bin_op.lhs);
3358 const result: MCValue = switch (dst_ty.zigTypeTag()) {
3337 const dst_ty = self.typeOf(bin_op.lhs);
3338 const result: MCValue = switch (dst_ty.zigTypeTag(mod)) {
33593339 .Vector => return self.fail("TODO implement mul_with_overflow for Vector type", .{}),
33603340 .Int => result: {
33613341 try self.spillEflagsIfOccupied();
33623342 try self.spillRegisters(&.{ .rax, .rdx });
33633343
3364 const dst_info = dst_ty.intInfo(self.target.*);
3344 const dst_info = dst_ty.intInfo(mod);
33653345 const cc: Condition = switch (dst_info.signedness) {
33663346 .unsigned => .c,
33673347 .signed => .o,
......@@ -3369,16 +3349,13 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
33693349
33703350 const lhs_active_bits = self.activeIntBits(bin_op.lhs);
33713351 const rhs_active_bits = self.activeIntBits(bin_op.rhs);
3372 var src_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dst_info.signedness) {
3373 .signed => .int_signed,
3374 .unsigned => .int_unsigned,
3375 } }, .data = math.max3(lhs_active_bits, rhs_active_bits, dst_info.bits / 2) };
3376 const src_ty = Type.initPayload(&src_pl.base);
3352 const src_bits = math.max3(lhs_active_bits, rhs_active_bits, dst_info.bits / 2);
3353 const src_ty = try mod.intType(dst_info.signedness, src_bits);
33773354
33783355 const lhs = try self.resolveInst(bin_op.lhs);
33793356 const rhs = try self.resolveInst(bin_op.rhs);
33803357
3381 const tuple_ty = self.air.typeOfIndex(inst);
3358 const tuple_ty = self.typeOfIndex(inst);
33823359 const extra_bits = if (dst_info.bits <= 64)
33833360 self.regExtraBits(dst_ty)
33843361 else
......@@ -3391,27 +3368,27 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
33913368 break :result .{ .register_overflow = .{ .reg = reg, .eflags = cc } };
33923369 } else {
33933370 const frame_index =
3394 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));
3371 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
33953372 try self.genSetFrameTruncatedOverflowCompare(tuple_ty, frame_index, partial_mcv, cc);
33963373 break :result .{ .load_frame = .{ .index = frame_index } };
33973374 },
33983375 else => {
33993376 // For now, this is the only supported multiply that doesn't fit in a register.
3400 assert(dst_info.bits <= 128 and src_pl.data == 64);
3377 assert(dst_info.bits <= 128 and src_bits == 64);
34013378
34023379 const frame_index =
3403 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, self.target.*));
3380 try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod));
34043381 if (dst_info.bits >= lhs_active_bits + rhs_active_bits) {
34053382 try self.genSetMem(
34063383 .{ .frame = frame_index },
3407 @intCast(i32, tuple_ty.structFieldOffset(0, self.target.*)),
3408 tuple_ty.structFieldType(0),
3384 @intCast(i32, tuple_ty.structFieldOffset(0, mod)),
3385 tuple_ty.structFieldType(0, mod),
34093386 partial_mcv,
34103387 );
34113388 try self.genSetMem(
34123389 .{ .frame = frame_index },
3413 @intCast(i32, tuple_ty.structFieldOffset(1, self.target.*)),
3414 tuple_ty.structFieldType(1),
3390 @intCast(i32, tuple_ty.structFieldOffset(1, mod)),
3391 tuple_ty.structFieldType(1, mod),
34153392 .{ .immediate = 0 }, // cc being set is impossible
34163393 );
34173394 } else try self.genSetFrameTruncatedOverflowCompare(
......@@ -3433,7 +3410,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
34333410/// Clobbers .rax and .rdx registers.
34343411/// Quotient is saved in .rax and remainder in .rdx.
34353412fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue, rhs: MCValue) !void {
3436 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3413 const mod = self.bin_file.options.module.?;
3414 const abi_size = @intCast(u32, ty.abiSize(mod));
34373415 if (abi_size > 8) {
34383416 return self.fail("TODO implement genIntMulDivOpMir for ABI size larger than 8", .{});
34393417 }
......@@ -3472,8 +3450,9 @@ fn genIntMulDivOpMir(self: *Self, tag: Mir.Inst.FixedTag, ty: Type, lhs: MCValue
34723450/// Always returns a register.
34733451/// Clobbers .rax and .rdx registers.
34743452fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCValue {
3475 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
3476 const int_info = ty.intInfo(self.target.*);
3453 const mod = self.bin_file.options.module.?;
3454 const abi_size = @intCast(u32, ty.abiSize(mod));
3455 const int_info = ty.intInfo(mod);
34773456 const dividend: Register = switch (lhs) {
34783457 .register => |reg| reg,
34793458 else => try self.copyToTmpRegister(ty, lhs),
......@@ -3531,8 +3510,8 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void {
35313510 try self.register_manager.getReg(.rcx, null);
35323511 const lhs = try self.resolveInst(bin_op.lhs);
35333512 const rhs = try self.resolveInst(bin_op.rhs);
3534 const lhs_ty = self.air.typeOf(bin_op.lhs);
3535 const rhs_ty = self.air.typeOf(bin_op.rhs);
3513 const lhs_ty = self.typeOf(bin_op.lhs);
3514 const rhs_ty = self.typeOf(bin_op.rhs);
35363515
35373516 const result = try self.genShiftBinOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
35383517
......@@ -3549,7 +3528,7 @@ fn airShlSat(self: *Self, inst: Air.Inst.Index) !void {
35493528fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
35503529 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
35513530 const result: MCValue = result: {
3552 const pl_ty = self.air.typeOfIndex(inst);
3531 const pl_ty = self.typeOfIndex(inst);
35533532 const opt_mcv = try self.resolveInst(ty_op.operand);
35543533
35553534 if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) {
......@@ -3574,7 +3553,7 @@ fn airOptionalPayload(self: *Self, inst: Air.Inst.Index) !void {
35743553fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
35753554 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
35763555
3577 const dst_ty = self.air.typeOfIndex(inst);
3556 const dst_ty = self.typeOfIndex(inst);
35783557 const opt_mcv = try self.resolveInst(ty_op.operand);
35793558
35803559 const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))
......@@ -3585,14 +3564,15 @@ fn airOptionalPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
35853564}
35863565
35873566fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3567 const mod = self.bin_file.options.module.?;
35883568 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
35893569 const result = result: {
3590 const dst_ty = self.air.typeOfIndex(inst);
3591 const src_ty = self.air.typeOf(ty_op.operand);
3592 const opt_ty = src_ty.childType();
3570 const dst_ty = self.typeOfIndex(inst);
3571 const src_ty = self.typeOf(ty_op.operand);
3572 const opt_ty = src_ty.childType(mod);
35933573 const src_mcv = try self.resolveInst(ty_op.operand);
35943574
3595 if (opt_ty.optionalReprIsPayload()) {
3575 if (opt_ty.optionalReprIsPayload(mod)) {
35963576 break :result if (self.liveness.isUnused(inst))
35973577 .unreach
35983578 else if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
......@@ -3609,8 +3589,8 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
36093589 else
36103590 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
36113591
3612 const pl_ty = dst_ty.childType();
3613 const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*));
3592 const pl_ty = dst_ty.childType(mod);
3593 const pl_abi_size = @intCast(i32, pl_ty.abiSize(mod));
36143594 try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 });
36153595 break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;
36163596 };
......@@ -3618,22 +3598,23 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
36183598}
36193599
36203600fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
3601 const mod = self.bin_file.options.module.?;
36213602 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3622 const err_union_ty = self.air.typeOf(ty_op.operand);
3623 const err_ty = err_union_ty.errorUnionSet();
3624 const payload_ty = err_union_ty.errorUnionPayload();
3603 const err_union_ty = self.typeOf(ty_op.operand);
3604 const err_ty = err_union_ty.errorUnionSet(mod);
3605 const payload_ty = err_union_ty.errorUnionPayload(mod);
36253606 const operand = try self.resolveInst(ty_op.operand);
36263607
36273608 const result: MCValue = result: {
3628 if (err_ty.errorSetIsEmpty()) {
3609 if (err_ty.errorSetIsEmpty(mod)) {
36293610 break :result MCValue{ .immediate = 0 };
36303611 }
36313612
3632 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3613 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
36333614 break :result operand;
36343615 }
36353616
3636 const err_off = errUnionErrorOffset(payload_ty, self.target.*);
3617 const err_off = errUnionErrorOffset(payload_ty, mod);
36373618 switch (operand) {
36383619 .register => |reg| {
36393620 // TODO reuse operand
......@@ -3666,7 +3647,7 @@ fn airUnwrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
36663647
36673648fn airUnwrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
36683649 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3669 const err_union_ty = self.air.typeOf(ty_op.operand);
3650 const err_union_ty = self.typeOf(ty_op.operand);
36703651 const operand = try self.resolveInst(ty_op.operand);
36713652 const result = try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, operand);
36723653 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
......@@ -3678,12 +3659,13 @@ fn genUnwrapErrorUnionPayloadMir(
36783659 err_union_ty: Type,
36793660 err_union: MCValue,
36803661) !MCValue {
3681 const payload_ty = err_union_ty.errorUnionPayload();
3662 const mod = self.bin_file.options.module.?;
3663 const payload_ty = err_union_ty.errorUnionPayload(mod);
36823664
36833665 const result: MCValue = result: {
3684 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;
3666 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
36853667
3686 const payload_off = errUnionPayloadOffset(payload_ty, self.target.*);
3668 const payload_off = errUnionPayloadOffset(payload_ty, mod);
36873669 switch (err_union) {
36883670 .load_frame => |frame_addr| break :result .{ .load_frame = .{
36893671 .index = frame_addr.index,
......@@ -3720,9 +3702,10 @@ fn genUnwrapErrorUnionPayloadMir(
37203702
37213703// *(E!T) -> E
37223704fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
3705 const mod = self.bin_file.options.module.?;
37233706 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
37243707
3725 const src_ty = self.air.typeOf(ty_op.operand);
3708 const src_ty = self.typeOf(ty_op.operand);
37263709 const src_mcv = try self.resolveInst(ty_op.operand);
37273710 const src_reg = switch (src_mcv) {
37283711 .register => |reg| reg,
......@@ -3736,11 +3719,11 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
37363719 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
37373720 defer self.register_manager.unlockReg(dst_lock);
37383721
3739 const eu_ty = src_ty.childType();
3740 const pl_ty = eu_ty.errorUnionPayload();
3741 const err_ty = eu_ty.errorUnionSet();
3742 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
3743 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
3722 const eu_ty = src_ty.childType(mod);
3723 const pl_ty = eu_ty.errorUnionPayload(mod);
3724 const err_ty = eu_ty.errorUnionSet(mod);
3725 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
3726 const err_abi_size = @intCast(u32, err_ty.abiSize(mod));
37443727 try self.asmRegisterMemory(
37453728 .{ ._, .mov },
37463729 registerAlias(dst_reg, err_abi_size),
......@@ -3755,9 +3738,10 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void {
37553738
37563739// *(E!T) -> *T
37573740fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
3741 const mod = self.bin_file.options.module.?;
37583742 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
37593743
3760 const src_ty = self.air.typeOf(ty_op.operand);
3744 const src_ty = self.typeOf(ty_op.operand);
37613745 const src_mcv = try self.resolveInst(ty_op.operand);
37623746 const src_reg = switch (src_mcv) {
37633747 .register => |reg| reg,
......@@ -3766,7 +3750,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
37663750 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
37673751 defer self.register_manager.unlockReg(src_lock);
37683752
3769 const dst_ty = self.air.typeOfIndex(inst);
3753 const dst_ty = self.typeOfIndex(inst);
37703754 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
37713755 src_reg
37723756 else
......@@ -3775,10 +3759,10 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
37753759 const dst_lock = self.register_manager.lockReg(dst_reg);
37763760 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
37773761
3778 const eu_ty = src_ty.childType();
3779 const pl_ty = eu_ty.errorUnionPayload();
3780 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
3781 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
3762 const eu_ty = src_ty.childType(mod);
3763 const pl_ty = eu_ty.errorUnionPayload(mod);
3764 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3765 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
37823766 try self.asmRegisterMemory(
37833767 .{ ._, .lea },
37843768 registerAlias(dst_reg, dst_abi_size),
......@@ -3789,9 +3773,10 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void {
37893773}
37903774
37913775fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
3776 const mod = self.bin_file.options.module.?;
37923777 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
37933778 const result: MCValue = result: {
3794 const src_ty = self.air.typeOf(ty_op.operand);
3779 const src_ty = self.typeOf(ty_op.operand);
37953780 const src_mcv = try self.resolveInst(ty_op.operand);
37963781 const src_reg = switch (src_mcv) {
37973782 .register => |reg| reg,
......@@ -3800,11 +3785,11 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
38003785 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
38013786 defer self.register_manager.unlockReg(src_lock);
38023787
3803 const eu_ty = src_ty.childType();
3804 const pl_ty = eu_ty.errorUnionPayload();
3805 const err_ty = eu_ty.errorUnionSet();
3806 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
3807 const err_abi_size = @intCast(u32, err_ty.abiSize(self.target.*));
3788 const eu_ty = src_ty.childType(mod);
3789 const pl_ty = eu_ty.errorUnionPayload(mod);
3790 const err_ty = eu_ty.errorUnionSet(mod);
3791 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
3792 const err_abi_size = @intCast(u32, err_ty.abiSize(mod));
38083793 try self.asmMemoryImmediate(
38093794 .{ ._, .mov },
38103795 Memory.sib(Memory.PtrSize.fromSize(err_abi_size), .{
......@@ -3816,7 +3801,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
38163801
38173802 if (self.liveness.isUnused(inst)) break :result .unreach;
38183803
3819 const dst_ty = self.air.typeOfIndex(inst);
3804 const dst_ty = self.typeOfIndex(inst);
38203805 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
38213806 src_reg
38223807 else
......@@ -3824,8 +3809,8 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
38243809 const dst_lock = self.register_manager.lockReg(dst_reg);
38253810 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
38263811
3827 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
3828 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
3812 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3813 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
38293814 try self.asmRegisterMemory(
38303815 .{ ._, .lea },
38313816 registerAlias(dst_reg, dst_abi_size),
......@@ -3853,14 +3838,15 @@ fn airSaveErrReturnTraceIndex(self: *Self, inst: Air.Inst.Index) !void {
38533838}
38543839
38553840fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
3841 const mod = self.bin_file.options.module.?;
38563842 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
38573843 const result: MCValue = result: {
3858 const pl_ty = self.air.typeOf(ty_op.operand);
3859 if (!pl_ty.hasRuntimeBits()) break :result .{ .immediate = 1 };
3844 const pl_ty = self.typeOf(ty_op.operand);
3845 if (!pl_ty.hasRuntimeBits(mod)) break :result .{ .immediate = 1 };
38603846
3861 const opt_ty = self.air.typeOfIndex(inst);
3847 const opt_ty = self.typeOfIndex(inst);
38623848 const pl_mcv = try self.resolveInst(ty_op.operand);
3863 const same_repr = opt_ty.optionalReprIsPayload();
3849 const same_repr = opt_ty.optionalReprIsPayload(mod);
38643850 if (same_repr and self.reuseOperand(inst, ty_op.operand, 0, pl_mcv)) break :result pl_mcv;
38653851
38663852 const pl_lock: ?RegisterLock = switch (pl_mcv) {
......@@ -3873,7 +3859,7 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
38733859 try self.genCopy(pl_ty, opt_mcv, pl_mcv);
38743860
38753861 if (!same_repr) {
3876 const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*));
3862 const pl_abi_size = @intCast(i32, pl_ty.abiSize(mod));
38773863 switch (opt_mcv) {
38783864 else => unreachable,
38793865
......@@ -3900,19 +3886,20 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
39003886
39013887/// T to E!T
39023888fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
3889 const mod = self.bin_file.options.module.?;
39033890 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
39043891
39053892 const eu_ty = self.air.getRefType(ty_op.ty);
3906 const pl_ty = eu_ty.errorUnionPayload();
3907 const err_ty = eu_ty.errorUnionSet();
3893 const pl_ty = eu_ty.errorUnionPayload(mod);
3894 const err_ty = eu_ty.errorUnionSet(mod);
39083895 const operand = try self.resolveInst(ty_op.operand);
39093896
39103897 const result: MCValue = result: {
3911 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) break :result .{ .immediate = 0 };
3898 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .{ .immediate = 0 };
39123899
3913 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, self.target.*));
3914 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
3915 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
3900 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
3901 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3902 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
39163903 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, operand);
39173904 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, .{ .immediate = 0 });
39183905 break :result .{ .load_frame = .{ .index = frame_index } };
......@@ -3922,18 +3909,19 @@ fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
39223909
39233910/// E to E!T
39243911fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
3912 const mod = self.bin_file.options.module.?;
39253913 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
39263914
39273915 const eu_ty = self.air.getRefType(ty_op.ty);
3928 const pl_ty = eu_ty.errorUnionPayload();
3929 const err_ty = eu_ty.errorUnionSet();
3916 const pl_ty = eu_ty.errorUnionPayload(mod);
3917 const err_ty = eu_ty.errorUnionSet(mod);
39303918
39313919 const result: MCValue = result: {
3932 if (!pl_ty.hasRuntimeBitsIgnoreComptime()) break :result try self.resolveInst(ty_op.operand);
3920 if (!pl_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result try self.resolveInst(ty_op.operand);
39333921
3934 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, self.target.*));
3935 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, self.target.*));
3936 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, self.target.*));
3922 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(eu_ty, mod));
3923 const pl_off = @intCast(i32, errUnionPayloadOffset(pl_ty, mod));
3924 const err_off = @intCast(i32, errUnionErrorOffset(pl_ty, mod));
39373925 try self.genSetMem(.{ .frame = frame_index }, pl_off, pl_ty, .undef);
39383926 const operand = try self.resolveInst(ty_op.operand);
39393927 try self.genSetMem(.{ .frame = frame_index }, err_off, err_ty, operand);
......@@ -3949,7 +3937,7 @@ fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
39493937 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
39503938
39513939 const dst_mcv = try self.allocRegOrMem(inst, true);
3952 const dst_ty = self.air.typeOfIndex(inst);
3940 const dst_ty = self.typeOfIndex(inst);
39533941 try self.genCopy(dst_ty, dst_mcv, src_mcv);
39543942 break :result dst_mcv;
39553943 };
......@@ -3974,9 +3962,10 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void {
39743962}
39753963
39763964fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
3965 const mod = self.bin_file.options.module.?;
39773966 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
39783967
3979 const src_ty = self.air.typeOf(ty_op.operand);
3968 const src_ty = self.typeOf(ty_op.operand);
39803969 const src_mcv = try self.resolveInst(ty_op.operand);
39813970 const src_reg = switch (src_mcv) {
39823971 .register => |reg| reg,
......@@ -3985,7 +3974,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
39853974 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
39863975 defer self.register_manager.unlockReg(src_lock);
39873976
3988 const dst_ty = self.air.typeOfIndex(inst);
3977 const dst_ty = self.typeOfIndex(inst);
39893978 const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
39903979 src_reg
39913980 else
......@@ -3994,7 +3983,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
39943983 const dst_lock = self.register_manager.lockReg(dst_reg);
39953984 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
39963985
3997 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
3986 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
39983987 try self.asmRegisterMemory(
39993988 .{ ._, .lea },
40003989 registerAlias(dst_reg, dst_abi_size),
......@@ -4010,7 +3999,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void {
40103999fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void {
40114000 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
40124001
4013 const dst_ty = self.air.typeOfIndex(inst);
4002 const dst_ty = self.typeOfIndex(inst);
40144003 const opt_mcv = try self.resolveInst(ty_op.operand);
40154004
40164005 const dst_mcv = if (self.reuseOperand(inst, ty_op.operand, 0, opt_mcv))
......@@ -4041,7 +4030,8 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
40414030}
40424031
40434032fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
4044 const slice_ty = self.air.typeOf(lhs);
4033 const mod = self.bin_file.options.module.?;
4034 const slice_ty = self.typeOf(lhs);
40454035 const slice_mcv = try self.resolveInst(lhs);
40464036 const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) {
40474037 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4049,12 +4039,11 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
40494039 };
40504040 defer if (slice_mcv_lock) |lock| self.register_manager.unlockReg(lock);
40514041
4052 const elem_ty = slice_ty.childType();
4053 const elem_size = elem_ty.abiSize(self.target.*);
4054 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4055 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
4042 const elem_ty = slice_ty.childType(mod);
4043 const elem_size = elem_ty.abiSize(mod);
4044 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
40564045
4057 const index_ty = self.air.typeOf(rhs);
4046 const index_ty = self.typeOf(rhs);
40584047 const index_mcv = try self.resolveInst(rhs);
40594048 const index_mcv_lock: ?RegisterLock = switch (index_mcv) {
40604049 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4077,11 +4066,11 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
40774066}
40784067
40794068fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
4069 const mod = self.bin_file.options.module.?;
40804070 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4081 const slice_ty = self.air.typeOf(bin_op.lhs);
4071 const slice_ty = self.typeOf(bin_op.lhs);
40824072
4083 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4084 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
4073 const slice_ptr_field_type = slice_ty.slicePtrFieldType(mod);
40854074 const elem_ptr = try self.genSliceElemPtr(bin_op.lhs, bin_op.rhs);
40864075 const dst_mcv = try self.allocRegOrMem(inst, false);
40874076 try self.load(dst_mcv, slice_ptr_field_type, elem_ptr);
......@@ -4097,9 +4086,10 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void {
40974086}
40984087
40994088fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
4089 const mod = self.bin_file.options.module.?;
41004090 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
41014091
4102 const array_ty = self.air.typeOf(bin_op.lhs);
4092 const array_ty = self.typeOf(bin_op.lhs);
41034093 const array = try self.resolveInst(bin_op.lhs);
41044094 const array_lock: ?RegisterLock = switch (array) {
41054095 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4107,10 +4097,10 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
41074097 };
41084098 defer if (array_lock) |lock| self.register_manager.unlockReg(lock);
41094099
4110 const elem_ty = array_ty.childType();
4111 const elem_abi_size = elem_ty.abiSize(self.target.*);
4100 const elem_ty = array_ty.childType(mod);
4101 const elem_abi_size = elem_ty.abiSize(mod);
41124102
4113 const index_ty = self.air.typeOf(bin_op.rhs);
4103 const index_ty = self.typeOf(bin_op.rhs);
41144104 const index = try self.resolveInst(bin_op.rhs);
41154105 const index_lock: ?RegisterLock = switch (index) {
41164106 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4125,7 +4115,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
41254115 const addr_reg = try self.register_manager.allocReg(null, gp);
41264116 switch (array) {
41274117 .register => {
4128 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, self.target.*));
4118 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod));
41294119 try self.genSetMem(.{ .frame = frame_index }, 0, array_ty, array);
41304120 try self.asmRegisterMemory(
41314121 .{ ._, .lea },
......@@ -4162,15 +4152,16 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
41624152}
41634153
41644154fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
4155 const mod = self.bin_file.options.module.?;
41654156 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4166 const ptr_ty = self.air.typeOf(bin_op.lhs);
4157 const ptr_ty = self.typeOf(bin_op.lhs);
41674158
41684159 // this is identical to the `airPtrElemPtr` codegen expect here an
41694160 // additional `mov` is needed at the end to get the actual value
41704161
4171 const elem_ty = ptr_ty.elemType2();
4172 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
4173 const index_ty = self.air.typeOf(bin_op.rhs);
4162 const elem_ty = ptr_ty.elemType2(mod);
4163 const elem_abi_size = @intCast(u32, elem_ty.abiSize(mod));
4164 const index_ty = self.typeOf(bin_op.rhs);
41744165 const index_mcv = try self.resolveInst(bin_op.rhs);
41754166 const index_lock = switch (index_mcv) {
41764167 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4207,10 +4198,11 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
42074198}
42084199
42094200fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
4201 const mod = self.bin_file.options.module.?;
42104202 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
42114203 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
42124204
4213 const ptr_ty = self.air.typeOf(extra.lhs);
4205 const ptr_ty = self.typeOf(extra.lhs);
42144206 const ptr = try self.resolveInst(extra.lhs);
42154207 const ptr_lock: ?RegisterLock = switch (ptr) {
42164208 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4218,9 +4210,9 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
42184210 };
42194211 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
42204212
4221 const elem_ty = ptr_ty.elemType2();
4222 const elem_abi_size = elem_ty.abiSize(self.target.*);
4223 const index_ty = self.air.typeOf(extra.rhs);
4213 const elem_ty = ptr_ty.elemType2(mod);
4214 const elem_abi_size = elem_ty.abiSize(mod);
4215 const index_ty = self.typeOf(extra.rhs);
42244216 const index = try self.resolveInst(extra.rhs);
42254217 const index_lock: ?RegisterLock = switch (index) {
42264218 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -4239,11 +4231,12 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
42394231}
42404232
42414233fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4234 const mod = self.bin_file.options.module.?;
42424235 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
4243 const ptr_union_ty = self.air.typeOf(bin_op.lhs);
4244 const union_ty = ptr_union_ty.childType();
4245 const tag_ty = self.air.typeOf(bin_op.rhs);
4246 const layout = union_ty.unionGetLayout(self.target.*);
4236 const ptr_union_ty = self.typeOf(bin_op.lhs);
4237 const union_ty = ptr_union_ty.childType(mod);
4238 const tag_ty = self.typeOf(bin_op.rhs);
4239 const layout = union_ty.unionGetLayout(mod);
42474240
42484241 if (layout.tag_size == 0) {
42494242 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
......@@ -4275,20 +4268,19 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
42754268 break :blk MCValue{ .register = reg };
42764269 } else ptr;
42774270
4278 var ptr_tag_pl = ptr_union_ty.ptrInfo();
4279 ptr_tag_pl.data.pointee_type = tag_ty;
4280 const ptr_tag_ty = Type.initPayload(&ptr_tag_pl.base);
4271 const ptr_tag_ty = try mod.adjustPtrTypeChild(ptr_union_ty, tag_ty);
42814272 try self.store(ptr_tag_ty, adjusted_ptr, tag);
42824273
42834274 return self.finishAir(inst, .none, .{ bin_op.lhs, bin_op.rhs, .none });
42844275}
42854276
42864277fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
4278 const mod = self.bin_file.options.module.?;
42874279 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
42884280
4289 const tag_ty = self.air.typeOfIndex(inst);
4290 const union_ty = self.air.typeOf(ty_op.operand);
4291 const layout = union_ty.unionGetLayout(self.target.*);
4281 const tag_ty = self.typeOfIndex(inst);
4282 const union_ty = self.typeOf(ty_op.operand);
4283 const layout = union_ty.unionGetLayout(mod);
42924284
42934285 if (layout.tag_size == 0) {
42944286 return self.finishAir(inst, .none, .{ ty_op.operand, .none, .none });
......@@ -4302,7 +4294,7 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
43024294 };
43034295 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
43044296
4305 const tag_abi_size = tag_ty.abiSize(self.target.*);
4297 const tag_abi_size = tag_ty.abiSize(mod);
43064298 const dst_mcv: MCValue = blk: {
43074299 switch (operand) {
43084300 .load_frame => |frame_addr| {
......@@ -4337,10 +4329,11 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
43374329}
43384330
43394331fn airClz(self: *Self, inst: Air.Inst.Index) !void {
4332 const mod = self.bin_file.options.module.?;
43404333 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
43414334 const result = result: {
4342 const dst_ty = self.air.typeOfIndex(inst);
4343 const src_ty = self.air.typeOf(ty_op.operand);
4335 const dst_ty = self.typeOfIndex(inst);
4336 const src_ty = self.typeOf(ty_op.operand);
43444337
43454338 const src_mcv = try self.resolveInst(ty_op.operand);
43464339 const mat_src_mcv = switch (src_mcv) {
......@@ -4358,7 +4351,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
43584351 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
43594352 defer self.register_manager.unlockReg(dst_lock);
43604353
4361 const src_bits = src_ty.bitSize(self.target.*);
4354 const src_bits = src_ty.bitSize(mod);
43624355 if (self.hasFeature(.lzcnt)) {
43634356 if (src_bits <= 8) {
43644357 const wide_reg = try self.copyToTmpRegister(src_ty, mat_src_mcv);
......@@ -4405,7 +4398,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
44054398 }
44064399
44074400 if (src_bits > 64)
4408 return self.fail("TODO airClz of {}", .{src_ty.fmt(self.bin_file.options.module.?)});
4401 return self.fail("TODO airClz of {}", .{src_ty.fmt(mod)});
44094402 if (math.isPowerOfTwo(src_bits)) {
44104403 const imm_reg = try self.copyToTmpRegister(dst_ty, .{
44114404 .immediate = src_bits ^ (src_bits - 1),
......@@ -4422,7 +4415,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
44224415 try self.genBinOpMir(.{ ._, .bsr }, Type.u16, dst_mcv, .{ .register = wide_reg });
44234416 } else try self.genBinOpMir(.{ ._, .bsr }, src_ty, dst_mcv, mat_src_mcv);
44244417
4425 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
4418 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(mod)), 2);
44264419 try self.asmCmovccRegisterRegister(
44274420 registerAlias(dst_reg, cmov_abi_size),
44284421 registerAlias(imm_reg, cmov_abi_size),
......@@ -4449,7 +4442,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
44494442 .{ .register = wide_reg },
44504443 );
44514444
4452 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
4445 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(mod)), 2);
44534446 try self.asmCmovccRegisterRegister(
44544447 registerAlias(imm_reg, cmov_abi_size),
44554448 registerAlias(dst_reg, cmov_abi_size),
......@@ -4465,11 +4458,12 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void {
44654458}
44664459
44674460fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
4461 const mod = self.bin_file.options.module.?;
44684462 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
44694463 const result = result: {
4470 const dst_ty = self.air.typeOfIndex(inst);
4471 const src_ty = self.air.typeOf(ty_op.operand);
4472 const src_bits = src_ty.bitSize(self.target.*);
4464 const dst_ty = self.typeOfIndex(inst);
4465 const src_ty = self.typeOf(ty_op.operand);
4466 const src_bits = src_ty.bitSize(mod);
44734467
44744468 const src_mcv = try self.resolveInst(ty_op.operand);
44754469 const mat_src_mcv = switch (src_mcv) {
......@@ -4548,7 +4542,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
45484542 try self.genBinOpMir(.{ ._, .bsf }, Type.u16, dst_mcv, .{ .register = wide_reg });
45494543 } else try self.genBinOpMir(.{ ._, .bsf }, src_ty, dst_mcv, mat_src_mcv);
45504544
4551 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(self.target.*)), 2);
4545 const cmov_abi_size = @max(@intCast(u32, dst_ty.abiSize(mod)), 2);
45524546 try self.asmCmovccRegisterRegister(
45534547 registerAlias(dst_reg, cmov_abi_size),
45544548 registerAlias(width_reg, cmov_abi_size),
......@@ -4560,10 +4554,11 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void {
45604554}
45614555
45624556fn airPopcount(self: *Self, inst: Air.Inst.Index) !void {
4557 const mod = self.bin_file.options.module.?;
45634558 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
45644559 const result: MCValue = result: {
4565 const src_ty = self.air.typeOf(ty_op.operand);
4566 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
4560 const src_ty = self.typeOf(ty_op.operand);
4561 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
45674562 const src_mcv = try self.resolveInst(ty_op.operand);
45684563
45694564 if (self.hasFeature(.popcnt)) {
......@@ -4729,16 +4724,17 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m
47294724}
47304725
47314726fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
4727 const mod = self.bin_file.options.module.?;
47324728 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
47334729
4734 const src_ty = self.air.typeOf(ty_op.operand);
4730 const src_ty = self.typeOf(ty_op.operand);
47354731 const src_mcv = try self.resolveInst(ty_op.operand);
47364732
47374733 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, true);
47384734 switch (self.regExtraBits(src_ty)) {
47394735 0 => {},
47404736 else => |extra| try self.genBinOpMir(
4741 if (src_ty.isSignedInt()) .{ ._r, .sa } else .{ ._r, .sh },
4737 if (src_ty.isSignedInt(mod)) .{ ._r, .sa } else .{ ._r, .sh },
47424738 src_ty,
47434739 dst_mcv,
47444740 .{ .immediate = extra },
......@@ -4749,10 +4745,11 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
47494745}
47504746
47514747fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
4748 const mod = self.bin_file.options.module.?;
47524749 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
47534750
4754 const src_ty = self.air.typeOf(ty_op.operand);
4755 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
4751 const src_ty = self.typeOf(ty_op.operand);
4752 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
47564753 const src_mcv = try self.resolveInst(ty_op.operand);
47574754
47584755 const dst_mcv = try self.byteSwap(inst, src_ty, src_mcv, false);
......@@ -4847,7 +4844,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
48474844 switch (self.regExtraBits(src_ty)) {
48484845 0 => {},
48494846 else => |extra| try self.genBinOpMir(
4850 if (src_ty.isSignedInt()) .{ ._r, .sa } else .{ ._r, .sh },
4847 if (src_ty.isSignedInt(mod)) .{ ._r, .sa } else .{ ._r, .sh },
48514848 src_ty,
48524849 dst_mcv,
48534850 .{ .immediate = extra },
......@@ -4858,17 +4855,18 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void {
48584855}
48594856
48604857fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
4858 const mod = self.bin_file.options.module.?;
48614859 const tag = self.air.instructions.items(.tag)[inst];
48624860 const un_op = self.air.instructions.items(.data)[inst].un_op;
4863 const ty = self.air.typeOf(un_op);
4864 const abi_size: u32 = switch (ty.abiSize(self.target.*)) {
4861 const ty = self.typeOf(un_op);
4862 const abi_size: u32 = switch (ty.abiSize(mod)) {
48654863 1...16 => 16,
48664864 17...32 => 32,
48674865 else => return self.fail("TODO implement airFloatSign for {}", .{
4868 ty.fmt(self.bin_file.options.module.?),
4866 ty.fmt(mod),
48694867 }),
48704868 };
4871 const scalar_bits = ty.scalarType().floatBits(self.target.*);
4869 const scalar_bits = ty.scalarType(mod).floatBits(self.target.*);
48724870
48734871 const src_mcv = try self.resolveInst(un_op);
48744872 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
......@@ -4884,42 +4882,14 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
48844882 const dst_lock = self.register_manager.lockReg(dst_reg);
48854883 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
48864884
4887 var arena = std.heap.ArenaAllocator.init(self.gpa);
4888 defer arena.deinit();
4889
4890 const ExpectedContents = struct {
4891 scalar: union {
4892 i64: Value.Payload.I64,
4893 big: struct {
4894 limbs: [
4895 @max(
4896 std.math.big.int.Managed.default_capacity,
4897 std.math.big.int.calcTwosCompLimbCount(128),
4898 )
4899 ]std.math.big.Limb,
4900 pl: Value.Payload.BigInt,
4901 },
4902 },
4903 repeated: Value.Payload.SubValue,
4904 };
4905 var stack align(@alignOf(ExpectedContents)) =
4906 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
4885 const vec_ty = try mod.vectorType(.{
4886 .len = @divExact(abi_size * 8, scalar_bits),
4887 .child = (try mod.intType(.signed, scalar_bits)).ip_index,
4888 });
49074889
4908 var int_pl = Type.Payload.Bits{
4909 .base = .{ .tag = .int_signed },
4910 .data = scalar_bits,
4911 };
4912 var vec_pl = Type.Payload.Array{
4913 .base = .{ .tag = .vector },
4914 .data = .{
4915 .len = @divExact(abi_size * 8, scalar_bits),
4916 .elem_type = Type.initPayload(&int_pl.base),
4917 },
4918 };
4919 const vec_ty = Type.initPayload(&vec_pl.base);
49204890 const sign_val = switch (tag) {
4921 .neg => try vec_ty.minInt(stack.get(), self.target.*),
4922 .fabs => try vec_ty.maxInt(stack.get(), self.target.*),
4891 .neg => try vec_ty.minInt(mod, vec_ty),
4892 .fabs => try vec_ty.maxInt(mod, vec_ty),
49234893 else => unreachable,
49244894 };
49254895
......@@ -4993,7 +4963,7 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
49934963
49944964fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
49954965 const un_op = self.air.instructions.items(.data)[inst].un_op;
4996 const ty = self.air.typeOf(un_op);
4966 const ty = self.typeOf(un_op);
49974967
49984968 const src_mcv = try self.resolveInst(un_op);
49994969 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
......@@ -5008,25 +4978,26 @@ fn airRound(self: *Self, inst: Air.Inst.Index, mode: u4) !void {
50084978}
50094979
50104980fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4) !void {
4981 const mod = self.bin_file.options.module.?;
50114982 if (!self.hasFeature(.sse4_1))
50124983 return self.fail("TODO implement genRound without sse4_1 feature", .{});
50134984
5014 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag()) {
4985 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
50154986 .Float => switch (ty.floatBits(self.target.*)) {
50164987 32 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },
50174988 64 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },
50184989 16, 80, 128 => null,
50194990 else => unreachable,
50204991 },
5021 .Vector => switch (ty.childType().zigTypeTag()) {
5022 .Float => switch (ty.childType().floatBits(self.target.*)) {
5023 32 => switch (ty.vectorLen()) {
4992 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
4993 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
4994 32 => switch (ty.vectorLen(mod)) {
50244995 1 => if (self.hasFeature(.avx)) .{ .v_ss, .round } else .{ ._ss, .round },
50254996 2...4 => if (self.hasFeature(.avx)) .{ .v_ps, .round } else .{ ._ps, .round },
50264997 5...8 => if (self.hasFeature(.avx)) .{ .v_ps, .round } else null,
50274998 else => null,
50284999 },
5029 64 => switch (ty.vectorLen()) {
5000 64 => switch (ty.vectorLen(mod)) {
50305001 1 => if (self.hasFeature(.avx)) .{ .v_sd, .round } else .{ ._sd, .round },
50315002 2 => if (self.hasFeature(.avx)) .{ .v_pd, .round } else .{ ._pd, .round },
50325003 3...4 => if (self.hasFeature(.avx)) .{ .v_pd, .round } else null,
......@@ -5041,7 +5012,7 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
50415012 })) |tag| tag else return self.fail("TODO implement genRound for {}", .{
50425013 ty.fmt(self.bin_file.options.module.?),
50435014 });
5044 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5015 const abi_size = @intCast(u32, ty.abiSize(mod));
50455016 const dst_alias = registerAlias(dst_reg, abi_size);
50465017 switch (mir_tag[0]) {
50475018 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemoryImmediate(
......@@ -5078,9 +5049,10 @@ fn genRound(self: *Self, ty: Type, dst_reg: Register, src_mcv: MCValue, mode: u4
50785049}
50795050
50805051fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
5052 const mod = self.bin_file.options.module.?;
50815053 const un_op = self.air.instructions.items(.data)[inst].un_op;
5082 const ty = self.air.typeOf(un_op);
5083 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5054 const ty = self.typeOf(un_op);
5055 const abi_size = @intCast(u32, ty.abiSize(mod));
50845056
50855057 const src_mcv = try self.resolveInst(un_op);
50865058 const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
......@@ -5092,7 +5064,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
50925064 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
50935065
50945066 const result: MCValue = result: {
5095 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag()) {
5067 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) {
50965068 .Float => switch (ty.floatBits(self.target.*)) {
50975069 16 => if (self.hasFeature(.f16c)) {
50985070 const mat_src_reg = if (src_mcv.isRegister())
......@@ -5114,9 +5086,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
51145086 80, 128 => null,
51155087 else => unreachable,
51165088 },
5117 .Vector => switch (ty.childType().zigTypeTag()) {
5118 .Float => switch (ty.childType().floatBits(self.target.*)) {
5119 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {
5089 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
5090 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
5091 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen(mod)) {
51205092 1 => {
51215093 try self.asmRegisterRegister(
51225094 .{ .v_ps, .cvtph2 },
......@@ -5167,13 +5139,13 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
51675139 },
51685140 else => null,
51695141 } else null,
5170 32 => switch (ty.vectorLen()) {
5142 32 => switch (ty.vectorLen(mod)) {
51715143 1 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt },
51725144 2...4 => if (self.hasFeature(.avx)) .{ .v_ps, .sqrt } else .{ ._ps, .sqrt },
51735145 5...8 => if (self.hasFeature(.avx)) .{ .v_ps, .sqrt } else null,
51745146 else => null,
51755147 },
5176 64 => switch (ty.vectorLen()) {
5148 64 => switch (ty.vectorLen(mod)) {
51775149 1 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt },
51785150 2 => if (self.hasFeature(.avx)) .{ .v_pd, .sqrt } else .{ ._pd, .sqrt },
51795151 3...4 => if (self.hasFeature(.avx)) .{ .v_pd, .sqrt } else null,
......@@ -5186,7 +5158,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
51865158 },
51875159 else => unreachable,
51885160 })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{
5189 ty.fmt(self.bin_file.options.module.?),
5161 ty.fmt(mod),
51905162 });
51915163 switch (mir_tag[0]) {
51925164 .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
......@@ -5274,10 +5246,11 @@ fn reuseOperandAdvanced(
52745246}
52755247
52765248fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void {
5277 const ptr_info = ptr_ty.ptrInfo().data;
5249 const mod = self.bin_file.options.module.?;
5250 const ptr_info = ptr_ty.ptrInfo(mod);
52785251
52795252 const val_ty = ptr_info.pointee_type;
5280 const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*));
5253 const val_abi_size = @intCast(u32, val_ty.abiSize(mod));
52815254 const limb_abi_size: u32 = @min(val_abi_size, 8);
52825255 const limb_abi_bits = limb_abi_size * 8;
52835256 const val_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size);
......@@ -5347,7 +5320,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn
53475320}
53485321
53495322fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void {
5350 const dst_ty = ptr_ty.childType();
5323 const mod = self.bin_file.options.module.?;
5324 const dst_ty = ptr_ty.childType(mod);
53515325 switch (ptr_mcv) {
53525326 .none,
53535327 .unreach,
......@@ -5382,20 +5356,21 @@ fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerErro
53825356}
53835357
53845358fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
5359 const mod = self.bin_file.options.module.?;
53855360 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5386 const elem_ty = self.air.typeOfIndex(inst);
5361 const elem_ty = self.typeOfIndex(inst);
53875362 const result: MCValue = result: {
5388 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;
5363 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
53895364
53905365 try self.spillRegisters(&.{ .rdi, .rsi, .rcx });
53915366 const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx });
53925367 defer for (reg_locks) |lock| self.register_manager.unlockReg(lock);
53935368
5394 const ptr_ty = self.air.typeOf(ty_op.operand);
5395 const elem_size = elem_ty.abiSize(self.target.*);
5369 const ptr_ty = self.typeOf(ty_op.operand);
5370 const elem_size = elem_ty.abiSize(mod);
53965371
5397 const elem_rc = regClassForType(elem_ty);
5398 const ptr_rc = regClassForType(ptr_ty);
5372 const elem_rc = regClassForType(elem_ty, mod);
5373 const ptr_rc = regClassForType(ptr_ty, mod);
53995374
54005375 const ptr_mcv = try self.resolveInst(ty_op.operand);
54015376 const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and
......@@ -5405,7 +5380,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
54055380 else
54065381 try self.allocRegOrMem(inst, true);
54075382
5408 if (ptr_ty.ptrInfo().data.host_size > 0) {
5383 if (ptr_ty.ptrInfo(mod).host_size > 0) {
54095384 try self.packedLoad(dst_mcv, ptr_ty, ptr_mcv);
54105385 } else {
54115386 try self.load(dst_mcv, ptr_ty, ptr_mcv);
......@@ -5416,13 +5391,14 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
54165391}
54175392
54185393fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {
5419 const ptr_info = ptr_ty.ptrInfo().data;
5420 const src_ty = ptr_ty.childType();
5394 const mod = self.bin_file.options.module.?;
5395 const ptr_info = ptr_ty.ptrInfo(mod);
5396 const src_ty = ptr_ty.childType(mod);
54215397
54225398 const limb_abi_size: u16 = @min(ptr_info.host_size, 8);
54235399 const limb_abi_bits = limb_abi_size * 8;
54245400
5425 const src_bit_size = src_ty.bitSize(self.target.*);
5401 const src_bit_size = src_ty.bitSize(mod);
54265402 const src_byte_off = @intCast(i32, ptr_info.bit_offset / limb_abi_bits * limb_abi_size);
54275403 const src_bit_off = ptr_info.bit_offset % limb_abi_bits;
54285404
......@@ -5489,7 +5465,8 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In
54895465}
54905466
54915467fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void {
5492 const src_ty = ptr_ty.childType();
5468 const mod = self.bin_file.options.module.?;
5469 const src_ty = ptr_ty.childType(mod);
54935470 switch (ptr_mcv) {
54945471 .none,
54955472 .unreach,
......@@ -5524,6 +5501,7 @@ fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerErr
55245501}
55255502
55265503fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
5504 const mod = self.bin_file.options.module.?;
55275505 if (safety) {
55285506 // TODO if the value is undef, write 0xaa bytes to dest
55295507 } else {
......@@ -5531,9 +5509,9 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
55315509 }
55325510 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
55335511 const ptr_mcv = try self.resolveInst(bin_op.lhs);
5534 const ptr_ty = self.air.typeOf(bin_op.lhs);
5512 const ptr_ty = self.typeOf(bin_op.lhs);
55355513 const src_mcv = try self.resolveInst(bin_op.rhs);
5536 if (ptr_ty.ptrInfo().data.host_size > 0) {
5514 if (ptr_ty.ptrInfo(mod).host_size > 0) {
55375515 try self.packedStore(ptr_ty, ptr_mcv, src_mcv);
55385516 } else {
55395517 try self.store(ptr_ty, ptr_mcv, src_mcv);
......@@ -5555,14 +5533,15 @@ fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
55555533}
55565534
55575535fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
5558 const ptr_field_ty = self.air.typeOfIndex(inst);
5559 const ptr_container_ty = self.air.typeOf(operand);
5560 const container_ty = ptr_container_ty.childType();
5561 const field_offset = @intCast(i32, switch (container_ty.containerLayout()) {
5562 .Auto, .Extern => container_ty.structFieldOffset(index, self.target.*),
5563 .Packed => if (container_ty.zigTypeTag() == .Struct and
5564 ptr_field_ty.ptrInfo().data.host_size == 0)
5565 container_ty.packedStructFieldByteOffset(index, self.target.*)
5536 const mod = self.bin_file.options.module.?;
5537 const ptr_field_ty = self.typeOfIndex(inst);
5538 const ptr_container_ty = self.typeOf(operand);
5539 const container_ty = ptr_container_ty.childType(mod);
5540 const field_offset = @intCast(i32, switch (container_ty.containerLayout(mod)) {
5541 .Auto, .Extern => container_ty.structFieldOffset(index, mod),
5542 .Packed => if (container_ty.zigTypeTag(mod) == .Struct and
5543 ptr_field_ty.ptrInfo(mod).host_size == 0)
5544 container_ty.packedStructFieldByteOffset(index, mod)
55665545 else
55675546 0,
55685547 });
......@@ -5577,24 +5556,25 @@ fn fieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32
55775556}
55785557
55795558fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
5559 const mod = self.bin_file.options.module.?;
55805560 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
55815561 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
55825562 const result: MCValue = result: {
55835563 const operand = extra.struct_operand;
55845564 const index = extra.field_index;
55855565
5586 const container_ty = self.air.typeOf(operand);
5587 const container_rc = regClassForType(container_ty);
5588 const field_ty = container_ty.structFieldType(index);
5589 if (!field_ty.hasRuntimeBitsIgnoreComptime()) break :result .none;
5590 const field_rc = regClassForType(field_ty);
5566 const container_ty = self.typeOf(operand);
5567 const container_rc = regClassForType(container_ty, mod);
5568 const field_ty = container_ty.structFieldType(index, mod);
5569 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none;
5570 const field_rc = regClassForType(field_ty, mod);
55915571 const field_is_gp = field_rc.supersetOf(gp);
55925572
55935573 const src_mcv = try self.resolveInst(operand);
5594 const field_off = switch (container_ty.containerLayout()) {
5595 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, self.target.*) * 8),
5596 .Packed => if (container_ty.castTag(.@"struct")) |struct_obj|
5597 struct_obj.data.packedFieldBitOffset(self.target.*, index)
5574 const field_off = switch (container_ty.containerLayout(mod)) {
5575 .Auto, .Extern => @intCast(u32, container_ty.structFieldOffset(index, mod) * 8),
5576 .Packed => if (mod.typeToStruct(container_ty)) |struct_obj|
5577 struct_obj.packedFieldBitOffset(mod, index)
55985578 else
55995579 0,
56005580 };
......@@ -5611,7 +5591,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
56115591 break :result dst_mcv;
56125592 }
56135593
5614 const field_abi_size = @intCast(u32, field_ty.abiSize(self.target.*));
5594 const field_abi_size = @intCast(u32, field_ty.abiSize(mod));
56155595 const limb_abi_size: u32 = @min(field_abi_size, 8);
56165596 const limb_abi_bits = limb_abi_size * 8;
56175597 const field_byte_off = @intCast(i32, field_off / limb_abi_bits * limb_abi_size);
......@@ -5733,12 +5713,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
57335713}
57345714
57355715fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
5716 const mod = self.bin_file.options.module.?;
57365717 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
57375718 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
57385719
5739 const inst_ty = self.air.typeOfIndex(inst);
5740 const parent_ty = inst_ty.childType();
5741 const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, self.target.*));
5720 const inst_ty = self.typeOfIndex(inst);
5721 const parent_ty = inst_ty.childType(mod);
5722 const field_offset = @intCast(i32, parent_ty.structFieldOffset(extra.field_index, mod));
57425723
57435724 const src_mcv = try self.resolveInst(extra.field_ptr);
57445725 const dst_mcv = if (src_mcv.isRegisterOffset() and
......@@ -5751,9 +5732,10 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void {
57515732}
57525733
57535734fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue {
5754 const src_ty = self.air.typeOf(src_air);
5735 const mod = self.bin_file.options.module.?;
5736 const src_ty = self.typeOf(src_air);
57555737 const src_mcv = try self.resolveInst(src_air);
5756 if (src_ty.zigTypeTag() == .Vector) {
5738 if (src_ty.zigTypeTag(mod) == .Vector) {
57575739 return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(self.bin_file.options.module.?)});
57585740 }
57595741
......@@ -5786,28 +5768,22 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
57865768
57875769 switch (tag) {
57885770 .not => {
5789 const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(self.target.*), 8));
5790 const int_info = if (src_ty.tag() == .bool)
5771 const limb_abi_size = @intCast(u16, @min(src_ty.abiSize(mod), 8));
5772 const int_info = if (src_ty.ip_index == .bool_type)
57915773 std.builtin.Type.Int{ .signedness = .unsigned, .bits = 1 }
57925774 else
5793 src_ty.intInfo(self.target.*);
5775 src_ty.intInfo(mod);
57945776 var byte_off: i32 = 0;
57955777 while (byte_off * 8 < int_info.bits) : (byte_off += limb_abi_size) {
5796 var limb_pl = Type.Payload.Bits{
5797 .base = .{ .tag = switch (int_info.signedness) {
5798 .signed => .int_signed,
5799 .unsigned => .int_unsigned,
5800 } },
5801 .data = @intCast(u16, @min(int_info.bits - byte_off * 8, limb_abi_size * 8)),
5802 };
5803 const limb_ty = Type.initPayload(&limb_pl.base);
5778 const limb_bits = @intCast(u16, @min(int_info.bits - byte_off * 8, limb_abi_size * 8));
5779 const limb_ty = try mod.intType(int_info.signedness, limb_bits);
58045780 const limb_mcv = switch (byte_off) {
58055781 0 => dst_mcv,
58065782 else => dst_mcv.address().offset(byte_off).deref(),
58075783 };
58085784
5809 if (limb_pl.base.tag == .int_unsigned and self.regExtraBits(limb_ty) > 0) {
5810 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_pl.data);
5785 if (int_info.signedness == .unsigned and self.regExtraBits(limb_ty) > 0) {
5786 const mask = @as(u64, math.maxInt(u64)) >> @intCast(u6, 64 - limb_bits);
58115787 try self.genBinOpMir(.{ ._, .xor }, limb_ty, limb_mcv, .{ .immediate = mask });
58125788 } else try self.genUnOpMir(.{ ._, .not }, limb_ty, limb_mcv);
58135789 }
......@@ -5819,7 +5795,8 @@ fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air:
58195795}
58205796
58215797fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MCValue) !void {
5822 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
5798 const mod = self.bin_file.options.module.?;
5799 const abi_size = @intCast(u32, dst_ty.abiSize(mod));
58235800 if (abi_size > 8) return self.fail("TODO implement {} for {}", .{
58245801 mir_tag,
58255802 dst_ty.fmt(self.bin_file.options.module.?),
......@@ -5866,6 +5843,7 @@ fn genShiftBinOpMir(
58665843 lhs_mcv: MCValue,
58675844 shift_mcv: MCValue,
58685845) !void {
5846 const mod = self.bin_file.options.module.?;
58695847 const rhs_mcv: MCValue = rhs: {
58705848 switch (shift_mcv) {
58715849 .immediate => |imm| switch (imm) {
......@@ -5880,7 +5858,7 @@ fn genShiftBinOpMir(
58805858 break :rhs .{ .register = .rcx };
58815859 };
58825860
5883 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
5861 const abi_size = @intCast(u32, ty.abiSize(mod));
58845862 if (abi_size <= 8) {
58855863 switch (lhs_mcv) {
58865864 .register => |lhs_reg| switch (rhs_mcv) {
......@@ -6099,13 +6077,14 @@ fn genShiftBinOp(
60996077 lhs_ty: Type,
61006078 rhs_ty: Type,
61016079) !MCValue {
6102 if (lhs_ty.zigTypeTag() == .Vector) {
6080 const mod = self.bin_file.options.module.?;
6081 if (lhs_ty.zigTypeTag(mod) == .Vector) {
61036082 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});
61046083 }
61056084
6106 assert(rhs_ty.abiSize(self.target.*) == 1);
6085 assert(rhs_ty.abiSize(mod) == 1);
61076086
6108 const lhs_abi_size = lhs_ty.abiSize(self.target.*);
6087 const lhs_abi_size = lhs_ty.abiSize(mod);
61096088 if (lhs_abi_size > 16) {
61106089 return self.fail("TODO implement genShiftBinOp for {}", .{lhs_ty.fmtDebug()});
61116090 }
......@@ -6136,7 +6115,7 @@ fn genShiftBinOp(
61366115 break :dst dst_mcv;
61376116 };
61386117
6139 const signedness = lhs_ty.intInfo(self.target.*).signedness;
6118 const signedness = lhs_ty.intInfo(mod).signedness;
61406119 try self.genShiftBinOpMir(switch (air_tag) {
61416120 .shl, .shl_exact => switch (signedness) {
61426121 .signed => .{ ._l, .sa },
......@@ -6163,11 +6142,12 @@ fn genMulDivBinOp(
61636142 lhs: MCValue,
61646143 rhs: MCValue,
61656144) !MCValue {
6166 if (dst_ty.zigTypeTag() == .Vector or dst_ty.zigTypeTag() == .Float) {
6145 const mod = self.bin_file.options.module.?;
6146 if (dst_ty.zigTypeTag(mod) == .Vector or dst_ty.zigTypeTag(mod) == .Float) {
61676147 return self.fail("TODO implement genMulDivBinOp for {}", .{dst_ty.fmtDebug()});
61686148 }
6169 const dst_abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
6170 const src_abi_size = @intCast(u32, src_ty.abiSize(self.target.*));
6149 const dst_abi_size = @intCast(u32, dst_ty.abiSize(mod));
6150 const src_abi_size = @intCast(u32, src_ty.abiSize(mod));
61716151 if (switch (tag) {
61726152 else => unreachable,
61736153 .mul, .mulwrap => dst_abi_size != src_abi_size and dst_abi_size != src_abi_size * 2,
......@@ -6184,7 +6164,7 @@ fn genMulDivBinOp(
61846164 const reg_locks = self.register_manager.lockRegs(2, .{ .rax, .rdx });
61856165 defer for (reg_locks) |reg_lock| if (reg_lock) |lock| self.register_manager.unlockReg(lock);
61866166
6187 const signedness = ty.intInfo(self.target.*).signedness;
6167 const signedness = ty.intInfo(mod).signedness;
61886168 switch (tag) {
61896169 .mul,
61906170 .mulwrap,
......@@ -6338,13 +6318,14 @@ fn genBinOp(
63386318 lhs_air: Air.Inst.Ref,
63396319 rhs_air: Air.Inst.Ref,
63406320) !MCValue {
6341 const lhs_ty = self.air.typeOf(lhs_air);
6342 const rhs_ty = self.air.typeOf(rhs_air);
6343 const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*));
6321 const mod = self.bin_file.options.module.?;
6322 const lhs_ty = self.typeOf(lhs_air);
6323 const rhs_ty = self.typeOf(rhs_air);
6324 const abi_size = @intCast(u32, lhs_ty.abiSize(mod));
63446325
63456326 const maybe_mask_reg = switch (air_tag) {
63466327 else => null,
6347 .max, .min => if (lhs_ty.scalarType().isRuntimeFloat()) registerAlias(
6328 .max, .min => if (lhs_ty.scalarType(mod).isRuntimeFloat()) registerAlias(
63486329 if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: {
63496330 try self.register_manager.getReg(.xmm0, null);
63506331 break :mask .xmm0;
......@@ -6384,7 +6365,7 @@ fn genBinOp(
63846365
63856366 else => false,
63866367 };
6387 const vec_op = switch (lhs_ty.zigTypeTag()) {
6368 const vec_op = switch (lhs_ty.zigTypeTag(mod)) {
63886369 else => false,
63896370 .Float, .Vector => true,
63906371 };
......@@ -6456,7 +6437,7 @@ fn genBinOp(
64566437 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
64576438 defer self.register_manager.unlockReg(tmp_lock);
64586439
6459 const elem_size = lhs_ty.elemType2().abiSize(self.target.*);
6440 const elem_size = lhs_ty.elemType2(mod).abiSize(mod);
64606441 try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size });
64616442 try self.genBinOpMir(
64626443 switch (air_tag) {
......@@ -6506,7 +6487,7 @@ fn genBinOp(
65066487
65076488 try self.genBinOpMir(.{ ._, .cmp }, lhs_ty, dst_mcv, mat_src_mcv);
65086489
6509 const int_info = lhs_ty.intInfo(self.target.*);
6490 const int_info = lhs_ty.intInfo(mod);
65106491 const cc: Condition = switch (int_info.signedness) {
65116492 .unsigned => switch (air_tag) {
65126493 .min => .a,
......@@ -6520,7 +6501,7 @@ fn genBinOp(
65206501 },
65216502 };
65226503
6523 const cmov_abi_size = @max(@intCast(u32, lhs_ty.abiSize(self.target.*)), 2);
6504 const cmov_abi_size = @max(@intCast(u32, lhs_ty.abiSize(mod)), 2);
65246505 const tmp_reg = switch (dst_mcv) {
65256506 .register => |reg| reg,
65266507 else => try self.copyToTmpRegister(lhs_ty, dst_mcv),
......@@ -6581,7 +6562,7 @@ fn genBinOp(
65816562 }
65826563
65836564 const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size);
6584 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
6565 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
65856566 else => unreachable,
65866567 .Float => switch (lhs_ty.floatBits(self.target.*)) {
65876568 16 => if (self.hasFeature(.f16c)) {
......@@ -6657,10 +6638,10 @@ fn genBinOp(
66576638 80, 128 => null,
66586639 else => unreachable,
66596640 },
6660 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
6641 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
66616642 else => null,
6662 .Int => switch (lhs_ty.childType().intInfo(self.target.*).bits) {
6663 8 => switch (lhs_ty.vectorLen()) {
6643 .Int => switch (lhs_ty.childType(mod).intInfo(mod).bits) {
6644 8 => switch (lhs_ty.vectorLen(mod)) {
66646645 1...16 => switch (air_tag) {
66656646 .add,
66666647 .addwrap,
......@@ -6671,7 +6652,7 @@ fn genBinOp(
66716652 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
66726653 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
66736654 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6674 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6655 .min => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
66756656 .signed => if (self.hasFeature(.avx))
66766657 .{ .vp_b, .mins }
66776658 else if (self.hasFeature(.sse4_1))
......@@ -6685,7 +6666,7 @@ fn genBinOp(
66856666 else
66866667 null,
66876668 },
6688 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6669 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
66896670 .signed => if (self.hasFeature(.avx))
66906671 .{ .vp_b, .maxs }
66916672 else if (self.hasFeature(.sse4_1))
......@@ -6711,11 +6692,11 @@ fn genBinOp(
67116692 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
67126693 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
67136694 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6714 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6695 .min => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
67156696 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .mins } else null,
67166697 .unsigned => if (self.hasFeature(.avx)) .{ .vp_b, .minu } else null,
67176698 },
6718 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6699 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
67196700 .signed => if (self.hasFeature(.avx2)) .{ .vp_b, .maxs } else null,
67206701 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_b, .maxu } else null,
67216702 },
......@@ -6723,7 +6704,7 @@ fn genBinOp(
67236704 },
67246705 else => null,
67256706 },
6726 16 => switch (lhs_ty.vectorLen()) {
6707 16 => switch (lhs_ty.vectorLen(mod)) {
67276708 1...8 => switch (air_tag) {
67286709 .add,
67296710 .addwrap,
......@@ -6737,7 +6718,7 @@ fn genBinOp(
67376718 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
67386719 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
67396720 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6740 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6721 .min => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
67416722 .signed => if (self.hasFeature(.avx))
67426723 .{ .vp_w, .mins }
67436724 else
......@@ -6747,7 +6728,7 @@ fn genBinOp(
67476728 else
67486729 .{ .p_w, .minu },
67496730 },
6750 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6731 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
67516732 .signed => if (self.hasFeature(.avx))
67526733 .{ .vp_w, .maxs }
67536734 else
......@@ -6772,11 +6753,11 @@ fn genBinOp(
67726753 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
67736754 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
67746755 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6775 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6756 .min => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
67766757 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .mins } else null,
67776758 .unsigned => if (self.hasFeature(.avx)) .{ .vp_w, .minu } else null,
67786759 },
6779 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6760 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
67806761 .signed => if (self.hasFeature(.avx2)) .{ .vp_w, .maxs } else null,
67816762 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_w, .maxu } else null,
67826763 },
......@@ -6784,7 +6765,7 @@ fn genBinOp(
67846765 },
67856766 else => null,
67866767 },
6787 32 => switch (lhs_ty.vectorLen()) {
6768 32 => switch (lhs_ty.vectorLen(mod)) {
67886769 1...4 => switch (air_tag) {
67896770 .add,
67906771 .addwrap,
......@@ -6803,7 +6784,7 @@ fn genBinOp(
68036784 .bit_and => if (self.hasFeature(.avx)) .{ .vp_, .@"and" } else .{ .p_, .@"and" },
68046785 .bit_or => if (self.hasFeature(.avx)) .{ .vp_, .@"or" } else .{ .p_, .@"or" },
68056786 .xor => if (self.hasFeature(.avx)) .{ .vp_, .xor } else .{ .p_, .xor },
6806 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6787 .min => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
68076788 .signed => if (self.hasFeature(.avx))
68086789 .{ .vp_d, .mins }
68096790 else if (self.hasFeature(.sse4_1))
......@@ -6817,7 +6798,7 @@ fn genBinOp(
68176798 else
68186799 null,
68196800 },
6820 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6801 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
68216802 .signed => if (self.hasFeature(.avx))
68226803 .{ .vp_d, .maxs }
68236804 else if (self.hasFeature(.sse4_1))
......@@ -6846,11 +6827,11 @@ fn genBinOp(
68466827 .bit_and => if (self.hasFeature(.avx2)) .{ .vp_, .@"and" } else null,
68476828 .bit_or => if (self.hasFeature(.avx2)) .{ .vp_, .@"or" } else null,
68486829 .xor => if (self.hasFeature(.avx2)) .{ .vp_, .xor } else null,
6849 .min => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6830 .min => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
68506831 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .mins } else null,
68516832 .unsigned => if (self.hasFeature(.avx)) .{ .vp_d, .minu } else null,
68526833 },
6853 .max => switch (lhs_ty.childType().intInfo(self.target.*).signedness) {
6834 .max => switch (lhs_ty.childType(mod).intInfo(mod).signedness) {
68546835 .signed => if (self.hasFeature(.avx2)) .{ .vp_d, .maxs } else null,
68556836 .unsigned => if (self.hasFeature(.avx2)) .{ .vp_d, .maxu } else null,
68566837 },
......@@ -6858,7 +6839,7 @@ fn genBinOp(
68586839 },
68596840 else => null,
68606841 },
6861 64 => switch (lhs_ty.vectorLen()) {
6842 64 => switch (lhs_ty.vectorLen(mod)) {
68626843 1...2 => switch (air_tag) {
68636844 .add,
68646845 .addwrap,
......@@ -6887,8 +6868,8 @@ fn genBinOp(
68876868 },
68886869 else => null,
68896870 },
6890 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
6891 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen()) {
6871 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
6872 16 => if (self.hasFeature(.f16c)) switch (lhs_ty.vectorLen(mod)) {
68926873 1 => {
68936874 const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128();
68946875 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
......@@ -7063,7 +7044,7 @@ fn genBinOp(
70637044 },
70647045 else => null,
70657046 } else null,
7066 32 => switch (lhs_ty.vectorLen()) {
7047 32 => switch (lhs_ty.vectorLen(mod)) {
70677048 1 => switch (air_tag) {
70687049 .add => if (self.hasFeature(.avx)) .{ .v_ss, .add } else .{ ._ss, .add },
70697050 .sub => if (self.hasFeature(.avx)) .{ .v_ss, .sub } else .{ ._ss, .sub },
......@@ -7101,7 +7082,7 @@ fn genBinOp(
71017082 } else null,
71027083 else => null,
71037084 },
7104 64 => switch (lhs_ty.vectorLen()) {
7085 64 => switch (lhs_ty.vectorLen(mod)) {
71057086 1 => switch (air_tag) {
71067087 .add => if (self.hasFeature(.avx)) .{ .v_sd, .add } else .{ ._sd, .add },
71077088 .sub => if (self.hasFeature(.avx)) .{ .v_sd, .sub } else .{ ._sd, .sub },
......@@ -7206,21 +7187,21 @@ fn genBinOp(
72067187 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);
72077188
72087189 try self.asmRegisterRegisterRegisterImmediate(
7209 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7190 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
72107191 .Float => switch (lhs_ty.floatBits(self.target.*)) {
72117192 32 => .{ .v_ss, .cmp },
72127193 64 => .{ .v_sd, .cmp },
72137194 16, 80, 128 => null,
72147195 else => unreachable,
72157196 },
7216 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7217 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7218 32 => switch (lhs_ty.vectorLen()) {
7197 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7198 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7199 32 => switch (lhs_ty.vectorLen(mod)) {
72197200 1 => .{ .v_ss, .cmp },
72207201 2...8 => .{ .v_ps, .cmp },
72217202 else => null,
72227203 },
7223 64 => switch (lhs_ty.vectorLen()) {
7204 64 => switch (lhs_ty.vectorLen(mod)) {
72247205 1 => .{ .v_sd, .cmp },
72257206 2...4 => .{ .v_pd, .cmp },
72267207 else => null,
......@@ -7240,20 +7221,20 @@ fn genBinOp(
72407221 Immediate.u(3), // unord
72417222 );
72427223 try self.asmRegisterRegisterRegisterRegister(
7243 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7224 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
72447225 .Float => switch (lhs_ty.floatBits(self.target.*)) {
72457226 32 => .{ .v_ps, .blendv },
72467227 64 => .{ .v_pd, .blendv },
72477228 16, 80, 128 => null,
72487229 else => unreachable,
72497230 },
7250 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7251 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7252 32 => switch (lhs_ty.vectorLen()) {
7231 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7232 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7233 32 => switch (lhs_ty.vectorLen(mod)) {
72537234 1...8 => .{ .v_ps, .blendv },
72547235 else => null,
72557236 },
7256 64 => switch (lhs_ty.vectorLen()) {
7237 64 => switch (lhs_ty.vectorLen(mod)) {
72577238 1...4 => .{ .v_pd, .blendv },
72587239 else => null,
72597240 },
......@@ -7274,21 +7255,21 @@ fn genBinOp(
72747255 } else {
72757256 const has_blend = self.hasFeature(.sse4_1);
72767257 try self.asmRegisterRegisterImmediate(
7277 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7258 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
72787259 .Float => switch (lhs_ty.floatBits(self.target.*)) {
72797260 32 => .{ ._ss, .cmp },
72807261 64 => .{ ._sd, .cmp },
72817262 16, 80, 128 => null,
72827263 else => unreachable,
72837264 },
7284 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7285 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7286 32 => switch (lhs_ty.vectorLen()) {
7265 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7266 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7267 32 => switch (lhs_ty.vectorLen(mod)) {
72877268 1 => .{ ._ss, .cmp },
72887269 2...4 => .{ ._ps, .cmp },
72897270 else => null,
72907271 },
7291 64 => switch (lhs_ty.vectorLen()) {
7272 64 => switch (lhs_ty.vectorLen(mod)) {
72927273 1 => .{ ._sd, .cmp },
72937274 2 => .{ ._pd, .cmp },
72947275 else => null,
......@@ -7307,20 +7288,20 @@ fn genBinOp(
73077288 Immediate.u(if (has_blend) 3 else 7), // unord, ord
73087289 );
73097290 if (has_blend) try self.asmRegisterRegisterRegister(
7310 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7291 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
73117292 .Float => switch (lhs_ty.floatBits(self.target.*)) {
73127293 32 => .{ ._ps, .blendv },
73137294 64 => .{ ._pd, .blendv },
73147295 16, 80, 128 => null,
73157296 else => unreachable,
73167297 },
7317 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7318 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7319 32 => switch (lhs_ty.vectorLen()) {
7298 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7299 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7300 32 => switch (lhs_ty.vectorLen(mod)) {
73207301 1...4 => .{ ._ps, .blendv },
73217302 else => null,
73227303 },
7323 64 => switch (lhs_ty.vectorLen()) {
7304 64 => switch (lhs_ty.vectorLen(mod)) {
73247305 1...2 => .{ ._pd, .blendv },
73257306 else => null,
73267307 },
......@@ -7338,20 +7319,20 @@ fn genBinOp(
73387319 mask_reg,
73397320 ) else {
73407321 try self.asmRegisterRegister(
7341 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7322 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
73427323 .Float => switch (lhs_ty.floatBits(self.target.*)) {
73437324 32 => .{ ._ps, .@"and" },
73447325 64 => .{ ._pd, .@"and" },
73457326 16, 80, 128 => null,
73467327 else => unreachable,
73477328 },
7348 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7349 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7350 32 => switch (lhs_ty.vectorLen()) {
7329 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7330 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7331 32 => switch (lhs_ty.vectorLen(mod)) {
73517332 1...4 => .{ ._ps, .@"and" },
73527333 else => null,
73537334 },
7354 64 => switch (lhs_ty.vectorLen()) {
7335 64 => switch (lhs_ty.vectorLen(mod)) {
73557336 1...2 => .{ ._pd, .@"and" },
73567337 else => null,
73577338 },
......@@ -7368,20 +7349,20 @@ fn genBinOp(
73687349 mask_reg,
73697350 );
73707351 try self.asmRegisterRegister(
7371 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7352 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
73727353 .Float => switch (lhs_ty.floatBits(self.target.*)) {
73737354 32 => .{ ._ps, .andn },
73747355 64 => .{ ._pd, .andn },
73757356 16, 80, 128 => null,
73767357 else => unreachable,
73777358 },
7378 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7379 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7380 32 => switch (lhs_ty.vectorLen()) {
7359 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7360 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7361 32 => switch (lhs_ty.vectorLen(mod)) {
73817362 1...4 => .{ ._ps, .andn },
73827363 else => null,
73837364 },
7384 64 => switch (lhs_ty.vectorLen()) {
7365 64 => switch (lhs_ty.vectorLen(mod)) {
73857366 1...2 => .{ ._pd, .andn },
73867367 else => null,
73877368 },
......@@ -7398,20 +7379,20 @@ fn genBinOp(
73987379 lhs_copy_reg.?,
73997380 );
74007381 try self.asmRegisterRegister(
7401 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7382 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag(mod)) {
74027383 .Float => switch (lhs_ty.floatBits(self.target.*)) {
74037384 32 => .{ ._ps, .@"or" },
74047385 64 => .{ ._pd, .@"or" },
74057386 16, 80, 128 => null,
74067387 else => unreachable,
74077388 },
7408 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7409 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7410 32 => switch (lhs_ty.vectorLen()) {
7389 .Vector => switch (lhs_ty.childType(mod).zigTypeTag(mod)) {
7390 .Float => switch (lhs_ty.childType(mod).floatBits(self.target.*)) {
7391 32 => switch (lhs_ty.vectorLen(mod)) {
74117392 1...4 => .{ ._ps, .@"or" },
74127393 else => null,
74137394 },
7414 64 => switch (lhs_ty.vectorLen()) {
7395 64 => switch (lhs_ty.vectorLen(mod)) {
74157396 1...2 => .{ ._pd, .@"or" },
74167397 else => null,
74177398 },
......@@ -7442,7 +7423,8 @@ fn genBinOpMir(
74427423 dst_mcv: MCValue,
74437424 src_mcv: MCValue,
74447425) !void {
7445 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
7426 const mod = self.bin_file.options.module.?;
7427 const abi_size = @intCast(u32, ty.abiSize(mod));
74467428 switch (dst_mcv) {
74477429 .none,
74487430 .unreach,
......@@ -7562,11 +7544,7 @@ fn genBinOpMir(
75627544 .load_got,
75637545 .load_tlv,
75647546 => {
7565 var ptr_pl = Type.Payload.ElemType{
7566 .base = .{ .tag = .single_const_pointer },
7567 .data = ty,
7568 };
7569 const ptr_ty = Type.initPayload(&ptr_pl.base);
7547 const ptr_ty = try mod.singleConstPtrType(ty);
75707548 const addr_reg = try self.copyToTmpRegister(ptr_ty, src_mcv.address());
75717549 return self.genBinOpMir(mir_tag, ty, dst_mcv, .{
75727550 .indirect = .{ .reg = addr_reg },
......@@ -7640,7 +7618,7 @@ fn genBinOpMir(
76407618 defer if (src_info) |info| self.register_manager.unlockReg(info.addr_lock);
76417619
76427620 const ty_signedness =
7643 if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned;
7621 if (ty.isAbiInt(mod)) ty.intInfo(mod).signedness else .unsigned;
76447622 const limb_ty = if (abi_size <= 8) ty else switch (ty_signedness) {
76457623 .signed => Type.usize,
76467624 .unsigned => Type.isize,
......@@ -7796,7 +7774,8 @@ fn genBinOpMir(
77967774/// Performs multi-operand integer multiplication between dst_mcv and src_mcv, storing the result in dst_mcv.
77977775/// Does not support byte-size operands.
77987776fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError!void {
7799 const abi_size = @intCast(u32, dst_ty.abiSize(self.target.*));
7777 const mod = self.bin_file.options.module.?;
7778 const abi_size = @intCast(u32, dst_ty.abiSize(mod));
78007779 switch (dst_mcv) {
78017780 .none,
78027781 .unreach,
......@@ -7896,6 +7875,7 @@ fn genIntMulComplexOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: M
78967875}
78977876
78987877fn airArg(self: *Self, inst: Air.Inst.Index) !void {
7878 const mod = self.bin_file.options.module.?;
78997879 // skip zero-bit arguments as they don't have a corresponding arg instruction
79007880 var arg_index = self.arg_index;
79017881 while (self.args[arg_index] == .none) arg_index += 1;
......@@ -7909,9 +7889,9 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
79097889 else => return self.fail("TODO implement arg for {}", .{dst_mcv}),
79107890 }
79117891
7912 const ty = self.air.typeOfIndex(inst);
7892 const ty = self.typeOfIndex(inst);
79137893 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
7914 const name = self.owner.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
7894 const name = self.owner.mod_fn.getParamName(mod, src_index);
79157895 try self.genArgDbgInfo(ty, name, dst_mcv);
79167896
79177897 break :result dst_mcv;
......@@ -7920,6 +7900,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
79207900}
79217901
79227902fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
7903 const mod = self.bin_file.options.module.?;
79237904 switch (self.debug_output) {
79247905 .dwarf => |dw| {
79257906 const loc: link.File.Dwarf.DeclState.DbgInfoLoc = switch (mcv) {
......@@ -7938,7 +7919,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
79387919 // TODO: this might need adjusting like the linkers do.
79397920 // Instead of flattening the owner and passing Decl.Index here we may
79407921 // want to special case LazySymbol in DWARF linker too.
7941 try dw.genArgDbgInfo(name, ty, self.owner.getDecl(), loc);
7922 try dw.genArgDbgInfo(name, ty, self.owner.getDecl(mod), loc);
79427923 },
79437924 .plan9 => {},
79447925 .none => {},
......@@ -7952,6 +7933,7 @@ fn genVarDbgInfo(
79527933 mcv: MCValue,
79537934 name: [:0]const u8,
79547935) !void {
7936 const mod = self.bin_file.options.module.?;
79557937 const is_ptr = switch (tag) {
79567938 .dbg_var_ptr => true,
79577939 .dbg_var_val => false,
......@@ -7982,7 +7964,7 @@ fn genVarDbgInfo(
79827964 // TODO: this might need adjusting like the linkers do.
79837965 // Instead of flattening the owner and passing Decl.Index here we may
79847966 // want to special case LazySymbol in DWARF linker too.
7985 try dw.genVarDbgInfo(name, ty, self.owner.getDecl(), is_ptr, loc);
7967 try dw.genVarDbgInfo(name, ty, self.owner.getDecl(mod), is_ptr, loc);
79867968 },
79877969 .plan9 => {},
79887970 .none => {},
......@@ -8022,20 +8004,23 @@ fn airFence(self: *Self, inst: Air.Inst.Index) !void {
80228004}
80238005
80248006fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void {
8007 const mod = self.bin_file.options.module.?;
80258008 if (modifier == .always_tail) return self.fail("TODO implement tail calls for x86_64", .{});
80268009 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
80278010 const callee = pl_op.operand;
80288011 const extra = self.air.extraData(Air.Call, pl_op.payload);
80298012 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
8030 const ty = self.air.typeOf(callee);
8013 const ty = self.typeOf(callee);
80318014
8032 const fn_ty = switch (ty.zigTypeTag()) {
8015 const fn_ty = switch (ty.zigTypeTag(mod)) {
80338016 .Fn => ty,
8034 .Pointer => ty.childType(),
8017 .Pointer => ty.childType(mod),
80358018 else => unreachable,
80368019 };
80378020
8038 var info = try self.resolveCallingConventionValues(fn_ty, args[fn_ty.fnParamLen()..], .call_frame);
8021 const fn_info = mod.typeToFunc(fn_ty).?;
8022
8023 var info = try self.resolveCallingConventionValues(fn_info, args[fn_info.param_types.len..], .call_frame);
80398024 defer info.deinit(self);
80408025
80418026 // We need a properly aligned and sized call frame to be able to call this function.
......@@ -8062,7 +8047,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
80628047 else => unreachable,
80638048 }
80648049 for (args, info.args) |arg, mc_arg| {
8065 const arg_ty = self.air.typeOf(arg);
8050 const arg_ty = self.typeOf(arg);
80668051 const arg_mcv = try self.resolveInst(arg);
80678052 switch (mc_arg) {
80688053 .none => {},
......@@ -8076,8 +8061,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
80768061 const ret_lock = switch (info.return_value.long) {
80778062 .none, .unreach => null,
80788063 .indirect => |reg_off| lock: {
8079 const ret_ty = fn_ty.fnReturnType();
8080 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, self.target.*));
8064 const ret_ty = fn_info.return_type.toType();
8065 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(ret_ty, mod));
80818066 try self.genSetReg(reg_off.reg, Type.usize, .{
80828067 .lea_frame = .{ .index = frame_index, .off = -reg_off.off },
80838068 });
......@@ -8089,7 +8074,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
80898074 defer if (ret_lock) |lock| self.register_manager.unlockReg(lock);
80908075
80918076 for (args, info.args) |arg, mc_arg| {
8092 const arg_ty = self.air.typeOf(arg);
8077 const arg_ty = self.typeOf(arg);
80938078 const arg_mcv = try self.resolveInst(arg);
80948079 switch (mc_arg) {
80958080 .none, .load_frame => {},
......@@ -8100,15 +8085,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81008085
81018086 // Due to incremental compilation, how function calls are generated depends
81028087 // on linking.
8103 const mod = self.bin_file.options.module.?;
8104 if (self.air.value(callee)) |func_value| {
8105 if (if (func_value.castTag(.function)) |func_payload|
8106 func_payload.data.owner_decl
8107 else if (func_value.castTag(.decl_ref)) |decl_ref_payload|
8108 decl_ref_payload.data
8109 else
8110 null) |owner_decl|
8111 {
8088 if (try self.air.value(callee, mod)) |func_value| {
8089 const func_key = mod.intern_pool.indexToKey(func_value.ip_index);
8090 if (switch (func_key) {
8091 .func => |func| mod.funcPtr(func.index).owner_decl,
8092 .ptr => |ptr| switch (ptr.addr) {
8093 .decl => |decl| decl,
8094 else => null,
8095 },
8096 else => null,
8097 }) |owner_decl| {
81128098 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
81138099 const atom_index = try elf_file.getOrCreateAtomForDecl(owner_decl);
81148100 const atom = elf_file.getAtom(atom_index);
......@@ -8141,10 +8127,9 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81418127 .disp = @intCast(i32, fn_got_addr),
81428128 }));
81438129 } else unreachable;
8144 } else if (func_value.castTag(.extern_fn)) |func_payload| {
8145 const extern_fn = func_payload.data;
8146 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);
8147 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
8130 } else if (func_value.getExternFunc(mod)) |extern_func| {
8131 const decl_name = mod.intern_pool.stringToSlice(mod.declPtr(extern_func.decl).name);
8132 const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name);
81488133 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
81498134 const atom_index = try self.owner.getSymbolIndex(self);
81508135 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
......@@ -8178,7 +8163,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81788163 return self.fail("TODO implement calling bitcasted functions", .{});
81798164 }
81808165 } else {
8181 assert(ty.zigTypeTag() == .Pointer);
8166 assert(ty.zigTypeTag(mod) == .Pointer);
81828167 const mcv = try self.resolveInst(callee);
81838168 try self.genSetReg(.rax, Type.usize, mcv);
81848169 try self.asmRegister(.{ ._, .call }, .rax);
......@@ -8193,9 +8178,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
81938178}
81948179
81958180fn airRet(self: *Self, inst: Air.Inst.Index) !void {
8181 const mod = self.bin_file.options.module.?;
81968182 const un_op = self.air.instructions.items(.data)[inst].un_op;
81978183 const operand = try self.resolveInst(un_op);
8198 const ret_ty = self.fn_type.fnReturnType();
8184 const ret_ty = self.fn_type.fnReturnType(mod);
81998185 switch (self.ret_mcv.short) {
82008186 .none => {},
82018187 .register => try self.genCopy(ret_ty, self.ret_mcv.short, operand),
......@@ -8219,7 +8205,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
82198205fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
82208206 const un_op = self.air.instructions.items(.data)[inst].un_op;
82218207 const ptr = try self.resolveInst(un_op);
8222 const ptr_ty = self.air.typeOf(un_op);
8208 const ptr_ty = self.typeOf(un_op);
82238209 switch (self.ret_mcv.short) {
82248210 .none => {},
82258211 .register => try self.load(self.ret_mcv.short, ptr_ty, ptr),
......@@ -8234,8 +8220,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
82348220}
82358221
82368222fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
8223 const mod = self.bin_file.options.module.?;
82378224 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8238 const ty = self.air.typeOf(bin_op.lhs);
8225 const ty = self.typeOf(bin_op.lhs);
82398226
82408227 try self.spillEflagsIfOccupied();
82418228 self.eflags_inst = inst;
......@@ -8255,9 +8242,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
82558242 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
82568243
82578244 const result = MCValue{
8258 .eflags = switch (ty.zigTypeTag()) {
8245 .eflags = switch (ty.zigTypeTag(mod)) {
82598246 else => result: {
8260 const abi_size = @intCast(u16, ty.abiSize(self.target.*));
8247 const abi_size = @intCast(u16, ty.abiSize(mod));
82618248 const may_flip: enum {
82628249 may_flip,
82638250 must_flip,
......@@ -8290,7 +8277,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
82908277 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
82918278
82928279 break :result Condition.fromCompareOperator(
8293 if (ty.isAbiInt()) ty.intInfo(self.target.*).signedness else .unsigned,
8280 if (ty.isAbiInt(mod)) ty.intInfo(mod).signedness else .unsigned,
82948281 result_op: {
82958282 const flipped_op = if (flipped) op.reverse() else op;
82968283 if (abi_size > 8) switch (flipped_op) {
......@@ -8404,7 +8391,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
84048391 try self.asmRegisterRegister(.{ .v_, .movshdup }, tmp2_reg, tmp1_reg);
84058392 try self.genBinOpMir(.{ ._ss, .ucomi }, ty, tmp1_mcv, tmp2_mcv);
84068393 } else return self.fail("TODO implement airCmp for {}", .{
8407 ty.fmt(self.bin_file.options.module.?),
8394 ty.fmt(mod),
84088395 }),
84098396 32 => try self.genBinOpMir(
84108397 .{ ._ss, .ucomi },
......@@ -8419,7 +8406,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
84198406 src_mcv,
84208407 ),
84218408 else => return self.fail("TODO implement airCmp for {}", .{
8422 ty.fmt(self.bin_file.options.module.?),
8409 ty.fmt(mod),
84238410 }),
84248411 }
84258412
......@@ -8453,8 +8440,8 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
84538440 try self.spillEflagsIfOccupied();
84548441 self.eflags_inst = inst;
84558442
8456 const op_ty = self.air.typeOf(un_op);
8457 const op_abi_size = @intCast(u32, op_ty.abiSize(self.target.*));
8443 const op_ty = self.typeOf(un_op);
8444 const op_abi_size = @intCast(u32, op_ty.abiSize(mod));
84588445 const op_mcv = try self.resolveInst(un_op);
84598446 const dst_reg = switch (op_mcv) {
84608447 .register => |reg| reg,
......@@ -8473,16 +8460,17 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void {
84738460 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
84748461 const extra = self.air.extraData(Air.Try, pl_op.payload);
84758462 const body = self.air.extra[extra.end..][0..extra.data.body_len];
8476 const err_union_ty = self.air.typeOf(pl_op.operand);
8463 const err_union_ty = self.typeOf(pl_op.operand);
84778464 const result = try self.genTry(inst, pl_op.operand, body, err_union_ty, false);
84788465 return self.finishAir(inst, result, .{ .none, .none, .none });
84798466}
84808467
84818468fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void {
8469 const mod = self.bin_file.options.module.?;
84828470 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
84838471 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
84848472 const body = self.air.extra[extra.end..][0..extra.data.body_len];
8485 const err_union_ty = self.air.typeOf(extra.data.ptr).childType();
8473 const err_union_ty = self.typeOf(extra.data.ptr).childType(mod);
84868474 const result = try self.genTry(inst, extra.data.ptr, body, err_union_ty, true);
84878475 return self.finishAir(inst, result, .{ .none, .none, .none });
84888476}
......@@ -8546,8 +8534,9 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
85468534}
85478535
85488536fn airDbgInline(self: *Self, inst: Air.Inst.Index) !void {
8549 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
8550 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
8537 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
8538 const mod = self.bin_file.options.module.?;
8539 const function = mod.funcPtr(ty_fn.func);
85518540 // TODO emit debug info for function change
85528541 _ = function;
85538542 return self.finishAir(inst, .unreach, .{ .none, .none, .none });
......@@ -8561,7 +8550,7 @@ fn airDbgBlock(self: *Self, inst: Air.Inst.Index) !void {
85618550fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
85628551 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
85638552 const operand = pl_op.operand;
8564 const ty = self.air.typeOf(operand);
8553 const ty = self.typeOf(operand);
85658554 const mcv = try self.resolveInst(operand);
85668555
85678556 const name = self.air.nullTerminatedString(pl_op.payload);
......@@ -8573,7 +8562,8 @@ fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
85738562}
85748563
85758564fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
8576 const abi_size = ty.abiSize(self.target.*);
8565 const mod = self.bin_file.options.module.?;
8566 const abi_size = ty.abiSize(mod);
85778567 switch (mcv) {
85788568 .eflags => |cc| {
85798569 // Here we map the opposites since the jump is to the false branch.
......@@ -8602,7 +8592,7 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
86028592fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
86038593 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
86048594 const cond = try self.resolveInst(pl_op.operand);
8605 const cond_ty = self.air.typeOf(pl_op.operand);
8595 const cond_ty = self.typeOf(pl_op.operand);
86068596 const extra = self.air.extraData(Air.CondBr, pl_op.payload);
86078597 const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len];
86088598 const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len];
......@@ -8646,6 +8636,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
86468636}
86478637
86488638fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MCValue {
8639 const mod = self.bin_file.options.module.?;
86498640 switch (opt_mcv) {
86508641 .register_overflow => |ro| return .{ .eflags = ro.eflags.negate() },
86518642 else => {},
......@@ -8654,14 +8645,12 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
86548645 try self.spillEflagsIfOccupied();
86558646 self.eflags_inst = inst;
86568647
8657 var pl_buf: Type.Payload.ElemType = undefined;
8658 const pl_ty = opt_ty.optionalChild(&pl_buf);
8648 const pl_ty = opt_ty.optionalChild(mod);
86598649
8660 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
8661 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload())
8662 .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
8650 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
8651 .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty }
86638652 else
8664 .{ .off = @intCast(i32, pl_ty.abiSize(self.target.*)), .ty = Type.bool };
8653 .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool };
86658654
86668655 switch (opt_mcv) {
86678656 .none,
......@@ -8681,14 +8670,14 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
86818670
86828671 .register => |opt_reg| {
86838672 if (some_info.off == 0) {
8684 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
8673 const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod));
86858674 const alias_reg = registerAlias(opt_reg, some_abi_size);
86868675 assert(some_abi_size * 8 == alias_reg.bitSize());
86878676 try self.asmRegisterRegister(.{ ._, .@"test" }, alias_reg, alias_reg);
86888677 return .{ .eflags = .z };
86898678 }
8690 assert(some_info.ty.tag() == .bool);
8691 const opt_abi_size = @intCast(u32, opt_ty.abiSize(self.target.*));
8679 assert(some_info.ty.ip_index == .bool_type);
8680 const opt_abi_size = @intCast(u32, opt_ty.abiSize(mod));
86928681 try self.asmRegisterImmediate(
86938682 .{ ._, .bt },
86948683 registerAlias(opt_reg, opt_abi_size),
......@@ -8707,7 +8696,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
87078696 defer self.register_manager.unlockReg(addr_reg_lock);
87088697
87098698 try self.genSetReg(addr_reg, Type.usize, opt_mcv.address());
8710 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
8699 const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod));
87118700 try self.asmMemoryImmediate(
87128701 .{ ._, .cmp },
87138702 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{
......@@ -8720,7 +8709,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
87208709 },
87218710
87228711 .indirect, .load_frame => {
8723 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
8712 const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod));
87248713 try self.asmMemoryImmediate(
87258714 .{ ._, .cmp },
87268715 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), switch (opt_mcv) {
......@@ -8742,18 +8731,17 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC
87428731}
87438732
87448733fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) !MCValue {
8734 const mod = self.bin_file.options.module.?;
87458735 try self.spillEflagsIfOccupied();
87468736 self.eflags_inst = inst;
87478737
8748 const opt_ty = ptr_ty.childType();
8749 var pl_buf: Type.Payload.ElemType = undefined;
8750 const pl_ty = opt_ty.optionalChild(&pl_buf);
8738 const opt_ty = ptr_ty.childType(mod);
8739 const pl_ty = opt_ty.optionalChild(mod);
87518740
8752 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
8753 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload())
8754 .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty }
8741 const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod))
8742 .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(mod) else pl_ty }
87558743 else
8756 .{ .off = @intCast(i32, pl_ty.abiSize(self.target.*)), .ty = Type.bool };
8744 .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool };
87578745
87588746 const ptr_reg = switch (ptr_mcv) {
87598747 .register => |reg| reg,
......@@ -8762,7 +8750,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
87628750 const ptr_lock = self.register_manager.lockReg(ptr_reg);
87638751 defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock);
87648752
8765 const some_abi_size = @intCast(u32, some_info.ty.abiSize(self.target.*));
8753 const some_abi_size = @intCast(u32, some_info.ty.abiSize(mod));
87668754 try self.asmMemoryImmediate(
87678755 .{ ._, .cmp },
87688756 Memory.sib(Memory.PtrSize.fromSize(some_abi_size), .{
......@@ -8775,9 +8763,10 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue)
87758763}
87768764
87778765fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
8778 const err_type = ty.errorUnionSet();
8766 const mod = self.bin_file.options.module.?;
8767 const err_type = ty.errorUnionSet(mod);
87798768
8780 if (err_type.errorSetIsEmpty()) {
8769 if (err_type.errorSetIsEmpty(mod)) {
87818770 return MCValue{ .immediate = 0 }; // always false
87828771 }
87838772
......@@ -8786,7 +8775,7 @@ fn isErr(self: *Self, maybe_inst: ?Air.Inst.Index, ty: Type, operand: MCValue) !
87868775 self.eflags_inst = inst;
87878776 }
87888777
8789 const err_off = errUnionErrorOffset(ty.errorUnionPayload(), self.target.*);
8778 const err_off = errUnionErrorOffset(ty.errorUnionPayload(mod), mod);
87908779 switch (operand) {
87918780 .register => |reg| {
87928781 const eu_lock = self.register_manager.lockReg(reg);
......@@ -8844,7 +8833,7 @@ fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCVa
88448833fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
88458834 const un_op = self.air.instructions.items(.data)[inst].un_op;
88468835 const operand = try self.resolveInst(un_op);
8847 const ty = self.air.typeOf(un_op);
8836 const ty = self.typeOf(un_op);
88488837 const result = try self.isNull(inst, ty, operand);
88498838 return self.finishAir(inst, result, .{ un_op, .none, .none });
88508839}
......@@ -8852,7 +8841,7 @@ fn airIsNull(self: *Self, inst: Air.Inst.Index) !void {
88528841fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
88538842 const un_op = self.air.instructions.items(.data)[inst].un_op;
88548843 const operand = try self.resolveInst(un_op);
8855 const ty = self.air.typeOf(un_op);
8844 const ty = self.typeOf(un_op);
88568845 const result = try self.isNullPtr(inst, ty, operand);
88578846 return self.finishAir(inst, result, .{ un_op, .none, .none });
88588847}
......@@ -8860,7 +8849,7 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
88608849fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
88618850 const un_op = self.air.instructions.items(.data)[inst].un_op;
88628851 const operand = try self.resolveInst(un_op);
8863 const ty = self.air.typeOf(un_op);
8852 const ty = self.typeOf(un_op);
88648853 const result = switch (try self.isNull(inst, ty, operand)) {
88658854 .eflags => |cc| .{ .eflags = cc.negate() },
88668855 else => unreachable,
......@@ -8871,7 +8860,7 @@ fn airIsNonNull(self: *Self, inst: Air.Inst.Index) !void {
88718860fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
88728861 const un_op = self.air.instructions.items(.data)[inst].un_op;
88738862 const operand = try self.resolveInst(un_op);
8874 const ty = self.air.typeOf(un_op);
8863 const ty = self.typeOf(un_op);
88758864 const result = switch (try self.isNullPtr(inst, ty, operand)) {
88768865 .eflags => |cc| .{ .eflags = cc.negate() },
88778866 else => unreachable,
......@@ -8882,12 +8871,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
88828871fn airIsErr(self: *Self, inst: Air.Inst.Index) !void {
88838872 const un_op = self.air.instructions.items(.data)[inst].un_op;
88848873 const operand = try self.resolveInst(un_op);
8885 const ty = self.air.typeOf(un_op);
8874 const ty = self.typeOf(un_op);
88868875 const result = try self.isErr(inst, ty, operand);
88878876 return self.finishAir(inst, result, .{ un_op, .none, .none });
88888877}
88898878
88908879fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8880 const mod = self.bin_file.options.module.?;
88918881 const un_op = self.air.instructions.items(.data)[inst].un_op;
88928882
88938883 const operand_ptr = try self.resolveInst(un_op);
......@@ -8905,10 +8895,10 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
89058895 break :blk try self.allocRegOrMem(inst, true);
89068896 }
89078897 };
8908 const ptr_ty = self.air.typeOf(un_op);
8898 const ptr_ty = self.typeOf(un_op);
89098899 try self.load(operand, ptr_ty, operand_ptr);
89108900
8911 const result = try self.isErr(inst, ptr_ty.childType(), operand);
8901 const result = try self.isErr(inst, ptr_ty.childType(mod), operand);
89128902
89138903 return self.finishAir(inst, result, .{ un_op, .none, .none });
89148904}
......@@ -8916,12 +8906,13 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
89168906fn airIsNonErr(self: *Self, inst: Air.Inst.Index) !void {
89178907 const un_op = self.air.instructions.items(.data)[inst].un_op;
89188908 const operand = try self.resolveInst(un_op);
8919 const ty = self.air.typeOf(un_op);
8909 const ty = self.typeOf(un_op);
89208910 const result = try self.isNonErr(inst, ty, operand);
89218911 return self.finishAir(inst, result, .{ un_op, .none, .none });
89228912}
89238913
89248914fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
8915 const mod = self.bin_file.options.module.?;
89258916 const un_op = self.air.instructions.items(.data)[inst].un_op;
89268917
89278918 const operand_ptr = try self.resolveInst(un_op);
......@@ -8939,10 +8930,10 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
89398930 break :blk try self.allocRegOrMem(inst, true);
89408931 }
89418932 };
8942 const ptr_ty = self.air.typeOf(un_op);
8933 const ptr_ty = self.typeOf(un_op);
89438934 try self.load(operand, ptr_ty, operand_ptr);
89448935
8945 const result = try self.isNonErr(inst, ptr_ty.childType(), operand);
8936 const result = try self.isNonErr(inst, ptr_ty.childType(mod), operand);
89468937
89478938 return self.finishAir(inst, result, .{ un_op, .none, .none });
89488939}
......@@ -9005,7 +8996,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void {
90058996fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void {
90068997 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
90078998 const condition = try self.resolveInst(pl_op.operand);
9008 const condition_ty = self.air.typeOf(pl_op.operand);
8999 const condition_ty = self.typeOf(pl_op.operand);
90099000 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
90109001 var extra_index: usize = switch_br.end;
90119002 var case_i: u32 = 0;
......@@ -9088,12 +9079,13 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {
90889079}
90899080
90909081fn airBr(self: *Self, inst: Air.Inst.Index) !void {
9082 const mod = self.bin_file.options.module.?;
90919083 const br = self.air.instructions.items(.data)[inst].br;
90929084 const src_mcv = try self.resolveInst(br.operand);
90939085
9094 const block_ty = self.air.typeOfIndex(br.block_inst);
9086 const block_ty = self.typeOfIndex(br.block_inst);
90959087 const block_unused =
9096 !block_ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(br.block_inst);
9088 !block_ty.hasRuntimeBitsIgnoreComptime(mod) or self.liveness.isUnused(br.block_inst);
90979089 const block_tracking = self.inst_tracking.getPtr(br.block_inst).?;
90989090 const block_data = self.blocks.getPtr(br.block_inst).?;
90999091 const first_br = block_data.relocs.items.len == 0;
......@@ -9216,7 +9208,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
92169208
92179209 const arg_mcv = try self.resolveInst(input);
92189210 try self.register_manager.getReg(reg, null);
9219 try self.genSetReg(reg, self.air.typeOf(input), arg_mcv);
9211 try self.genSetReg(reg, self.typeOf(input), arg_mcv);
92209212 }
92219213
92229214 {
......@@ -9402,7 +9394,8 @@ const MoveStrategy = union(enum) {
94029394 };
94039395};
94049396fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
9405 switch (ty.zigTypeTag()) {
9397 const mod = self.bin_file.options.module.?;
9398 switch (ty.zigTypeTag(mod)) {
94069399 else => return .{ .move = .{ ._, .mov } },
94079400 .Float => switch (ty.floatBits(self.target.*)) {
94089401 16 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
......@@ -9419,9 +9412,9 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
94199412 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
94209413 else => {},
94219414 },
9422 .Vector => switch (ty.childType().zigTypeTag()) {
9423 .Int => switch (ty.childType().intInfo(self.target.*).bits) {
9424 8 => switch (ty.vectorLen()) {
9415 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
9416 .Int => switch (ty.childType(mod).intInfo(mod).bits) {
9417 8 => switch (ty.vectorLen(mod)) {
94259418 1 => if (self.hasFeature(.avx)) return .{ .vex_insert_extract = .{
94269419 .insert = .{ .vp_b, .insr },
94279420 .extract = .{ .vp_b, .extr },
......@@ -9451,7 +9444,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
94519444 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
94529445 else => {},
94539446 },
9454 16 => switch (ty.vectorLen()) {
9447 16 => switch (ty.vectorLen(mod)) {
94559448 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
94569449 .insert = .{ .vp_w, .insr },
94579450 .extract = .{ .vp_w, .extr },
......@@ -9474,7 +9467,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
94749467 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
94759468 else => {},
94769469 },
9477 32 => switch (ty.vectorLen()) {
9470 32 => switch (ty.vectorLen(mod)) {
94789471 1 => return .{ .move = if (self.hasFeature(.avx))
94799472 .{ .v_d, .mov }
94809473 else
......@@ -9490,7 +9483,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
94909483 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
94919484 else => {},
94929485 },
9493 64 => switch (ty.vectorLen()) {
9486 64 => switch (ty.vectorLen(mod)) {
94949487 1 => return .{ .move = if (self.hasFeature(.avx))
94959488 .{ .v_q, .mov }
94969489 else
......@@ -9502,7 +9495,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
95029495 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
95039496 else => {},
95049497 },
9505 128 => switch (ty.vectorLen()) {
9498 128 => switch (ty.vectorLen(mod)) {
95069499 1 => return .{ .move = if (self.hasFeature(.avx))
95079500 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
95089501 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
......@@ -9510,15 +9503,15 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
95109503 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
95119504 else => {},
95129505 },
9513 256 => switch (ty.vectorLen()) {
9506 256 => switch (ty.vectorLen(mod)) {
95149507 1 => if (self.hasFeature(.avx))
95159508 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
95169509 else => {},
95179510 },
95189511 else => {},
95199512 },
9520 .Float => switch (ty.childType().floatBits(self.target.*)) {
9521 16 => switch (ty.vectorLen()) {
9513 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
9514 16 => switch (ty.vectorLen(mod)) {
95229515 1 => return if (self.hasFeature(.avx)) .{ .vex_insert_extract = .{
95239516 .insert = .{ .vp_w, .insr },
95249517 .extract = .{ .vp_w, .extr },
......@@ -9541,7 +9534,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
95419534 return .{ .move = if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu } },
95429535 else => {},
95439536 },
9544 32 => switch (ty.vectorLen()) {
9537 32 => switch (ty.vectorLen(mod)) {
95459538 1 => return .{ .move = if (self.hasFeature(.avx))
95469539 .{ .v_ss, .mov }
95479540 else
......@@ -9557,7 +9550,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
95579550 return .{ .move = if (aligned) .{ .v_ps, .mova } else .{ .v_ps, .movu } },
95589551 else => {},
95599552 },
9560 64 => switch (ty.vectorLen()) {
9553 64 => switch (ty.vectorLen(mod)) {
95619554 1 => return .{ .move = if (self.hasFeature(.avx))
95629555 .{ .v_sd, .mov }
95639556 else
......@@ -9569,7 +9562,7 @@ fn moveStrategy(self: *Self, ty: Type, aligned: bool) !MoveStrategy {
95699562 return .{ .move = if (aligned) .{ .v_pd, .mova } else .{ .v_pd, .movu } },
95709563 else => {},
95719564 },
9572 128 => switch (ty.vectorLen()) {
9565 128 => switch (ty.vectorLen(mod)) {
95739566 1 => return .{ .move = if (self.hasFeature(.avx))
95749567 if (aligned) .{ .v_, .movdqa } else .{ .v_, .movdqu }
95759568 else if (aligned) .{ ._, .movdqa } else .{ ._, .movdqu } },
......@@ -9647,7 +9640,8 @@ fn genCopy(self: *Self, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) InnerError
96479640}
96489641
96499642fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerError!void {
9650 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
9643 const mod = self.bin_file.options.module.?;
9644 const abi_size = @intCast(u32, ty.abiSize(mod));
96519645 if (abi_size * 8 > dst_reg.bitSize())
96529646 return self.fail("genSetReg called with a value larger than dst_reg", .{});
96539647 switch (src_mcv) {
......@@ -9730,7 +9724,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
97309724 .{ .register = try self.copyToTmpRegister(ty, src_mcv) },
97319725 ),
97329726 .sse => try self.asmRegisterRegister(
9733 if (@as(?Mir.Inst.FixedTag, switch (ty.scalarType().zigTypeTag()) {
9727 if (@as(?Mir.Inst.FixedTag, switch (ty.scalarType(mod).zigTypeTag(mod)) {
97349728 else => switch (abi_size) {
97359729 1...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
97369730 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
......@@ -9738,7 +9732,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
97389732 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,
97399733 else => null,
97409734 },
9741 .Float => switch (ty.scalarType().floatBits(self.target.*)) {
9735 .Float => switch (ty.scalarType(mod).floatBits(self.target.*)) {
97429736 16, 128 => switch (abi_size) {
97439737 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
97449738 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
......@@ -9789,7 +9783,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
97899783 .indirect => try self.moveStrategy(ty, false),
97909784 .load_frame => |frame_addr| try self.moveStrategy(
97919785 ty,
9792 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(self.target.*),
9786 self.getFrameAddrAlignment(frame_addr) >= ty.abiAlignment(mod),
97939787 ),
97949788 .lea_frame => .{ .move = .{ ._, .lea } },
97959789 else => unreachable,
......@@ -9821,7 +9815,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
98219815 switch (try self.moveStrategy(ty, mem.isAlignedGeneric(
98229816 u32,
98239817 @bitCast(u32, small_addr),
9824 ty.abiAlignment(self.target.*),
9818 ty.abiAlignment(mod),
98259819 ))) {
98269820 .move => |tag| try self.asmRegisterMemory(tag, dst_alias, src_mem),
98279821 .insert_extract => |ie| try self.asmRegisterMemoryImmediate(
......@@ -9839,7 +9833,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
98399833 ),
98409834 }
98419835 },
9842 .load_direct => |sym_index| switch (ty.zigTypeTag()) {
9836 .load_direct => |sym_index| switch (ty.zigTypeTag(mod)) {
98439837 else => {
98449838 const atom_index = try self.owner.getSymbolIndex(self);
98459839 _ = try self.addInst(.{
......@@ -9933,7 +9927,8 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
99339927}
99349928
99359929fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCValue) InnerError!void {
9936 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
9930 const mod = self.bin_file.options.module.?;
9931 const abi_size = @intCast(u32, ty.abiSize(mod));
99379932 const dst_ptr_mcv: MCValue = switch (base) {
99389933 .none => .{ .immediate = @bitCast(u64, @as(i64, disp)) },
99399934 .reg => |base_reg| .{ .register_offset = .{ .reg = base_reg, .off = disp } },
......@@ -9945,7 +9940,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
99459940 try self.genInlineMemset(dst_ptr_mcv, .{ .immediate = 0xaa }, .{ .immediate = abi_size }),
99469941 .immediate => |imm| switch (abi_size) {
99479942 1, 2, 4 => {
9948 const immediate = if (ty.isSignedInt())
9943 const immediate = if (ty.isSignedInt(mod))
99499944 Immediate.s(@truncate(i32, @bitCast(i64, imm)))
99509945 else
99519946 Immediate.u(@intCast(u32, imm));
......@@ -9967,7 +9962,7 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
99679962 while (offset < abi_size) : (offset += 4) try self.asmMemoryImmediate(
99689963 .{ ._, .mov },
99699964 Memory.sib(.dword, .{ .base = base, .disp = disp + offset }),
9970 if (ty.isSignedInt())
9965 if (ty.isSignedInt(mod))
99719966 Immediate.s(@truncate(
99729967 i32,
99739968 @bitCast(i64, imm) >> (math.cast(u6, offset * 8) orelse 63),
......@@ -9991,19 +9986,19 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
99919986 .none => mem.isAlignedGeneric(
99929987 u32,
99939988 @bitCast(u32, disp),
9994 ty.abiAlignment(self.target.*),
9989 ty.abiAlignment(mod),
99959990 ),
99969991 .reg => |reg| switch (reg) {
99979992 .es, .cs, .ss, .ds => mem.isAlignedGeneric(
99989993 u32,
99999994 @bitCast(u32, disp),
10000 ty.abiAlignment(self.target.*),
9995 ty.abiAlignment(mod),
100019996 ),
100029997 else => false,
100039998 },
100049999 .frame => |frame_index| self.getFrameAddrAlignment(
1000510000 .{ .index = frame_index, .off = disp },
10006 ) >= ty.abiAlignment(self.target.*),
10001 ) >= ty.abiAlignment(mod),
1000710002 })) {
1000810003 .move => |tag| try self.asmMemoryRegister(tag, dst_mem, src_alias),
1000910004 .insert_extract, .vex_insert_extract => |ie| try self.asmMemoryRegisterImmediate(
......@@ -10017,14 +10012,14 @@ fn genSetMem(self: *Self, base: Memory.Base, disp: i32, ty: Type, src_mcv: MCVal
1001710012 .register_overflow => |ro| {
1001810013 try self.genSetMem(
1001910014 base,
10020 disp + @intCast(i32, ty.structFieldOffset(0, self.target.*)),
10021 ty.structFieldType(0),
10015 disp + @intCast(i32, ty.structFieldOffset(0, mod)),
10016 ty.structFieldType(0, mod),
1002210017 .{ .register = ro.reg },
1002310018 );
1002410019 try self.genSetMem(
1002510020 base,
10026 disp + @intCast(i32, ty.structFieldOffset(1, self.target.*)),
10027 ty.structFieldType(1),
10021 disp + @intCast(i32, ty.structFieldOffset(1, mod)),
10022 ty.structFieldType(1, mod),
1002810023 .{ .eflags = ro.eflags },
1002910024 );
1003010025 },
......@@ -10138,7 +10133,7 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
1013810133 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
1013910134
1014010135 const dst_mcv = try self.allocRegOrMem(inst, true);
10141 const dst_ty = self.air.typeOfIndex(inst);
10136 const dst_ty = self.typeOfIndex(inst);
1014210137 try self.genCopy(dst_ty, dst_mcv, src_mcv);
1014310138 break :result dst_mcv;
1014410139 };
......@@ -10146,13 +10141,14 @@ fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
1014610141}
1014710142
1014810143fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
10144 const mod = self.bin_file.options.module.?;
1014910145 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
10150 const dst_ty = self.air.typeOfIndex(inst);
10151 const src_ty = self.air.typeOf(ty_op.operand);
10146 const dst_ty = self.typeOfIndex(inst);
10147 const src_ty = self.typeOf(ty_op.operand);
1015210148
1015310149 const result = result: {
10154 const dst_rc = regClassForType(dst_ty);
10155 const src_rc = regClassForType(src_ty);
10150 const dst_rc = regClassForType(dst_ty, mod);
10151 const src_rc = regClassForType(src_ty, mod);
1015610152 const src_mcv = try self.resolveInst(ty_op.operand);
1015710153
1015810154 const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null;
......@@ -10172,13 +10168,13 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1017210168 };
1017310169
1017410170 const dst_signedness =
10175 if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned;
10171 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;
1017610172 const src_signedness =
10177 if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned;
10173 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
1017810174 if (dst_signedness == src_signedness) break :result dst_mcv;
1017910175
10180 const abi_size = @intCast(u16, dst_ty.abiSize(self.target.*));
10181 const bit_size = @intCast(u16, dst_ty.bitSize(self.target.*));
10176 const abi_size = @intCast(u16, dst_ty.abiSize(mod));
10177 const bit_size = @intCast(u16, dst_ty.bitSize(mod));
1018210178 if (abi_size * 8 <= bit_size) break :result dst_mcv;
1018310179
1018410180 const dst_limbs_len = math.divCeil(i32, bit_size, 64) catch unreachable;
......@@ -10192,14 +10188,7 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1019210188 const high_lock = self.register_manager.lockReg(high_reg);
1019310189 defer if (high_lock) |lock| self.register_manager.unlockReg(lock);
1019410190
10195 var high_pl = Type.Payload.Bits{
10196 .base = .{ .tag = switch (dst_signedness) {
10197 .signed => .int_signed,
10198 .unsigned => .int_unsigned,
10199 } },
10200 .data = bit_size % 64,
10201 };
10202 const high_ty = Type.initPayload(&high_pl.base);
10191 const high_ty = try mod.intType(dst_signedness, bit_size % 64);
1020310192
1020410193 try self.truncateRegister(high_ty, high_reg);
1020510194 if (!dst_mcv.isRegister()) try self.genCopy(
......@@ -10213,19 +10202,20 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void {
1021310202}
1021410203
1021510204fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
10205 const mod = self.bin_file.options.module.?;
1021610206 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1021710207
10218 const slice_ty = self.air.typeOfIndex(inst);
10219 const ptr_ty = self.air.typeOf(ty_op.operand);
10208 const slice_ty = self.typeOfIndex(inst);
10209 const ptr_ty = self.typeOf(ty_op.operand);
1022010210 const ptr = try self.resolveInst(ty_op.operand);
10221 const array_ty = ptr_ty.childType();
10222 const array_len = array_ty.arrayLen();
10211 const array_ty = ptr_ty.childType(mod);
10212 const array_len = array_ty.arrayLen(mod);
1022310213
10224 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, self.target.*));
10214 const frame_index = try self.allocFrameIndex(FrameAlloc.initType(slice_ty, mod));
1022510215 try self.genSetMem(.{ .frame = frame_index }, 0, ptr_ty, ptr);
1022610216 try self.genSetMem(
1022710217 .{ .frame = frame_index },
10228 @intCast(i32, ptr_ty.abiSize(self.target.*)),
10218 @intCast(i32, ptr_ty.abiSize(mod)),
1022910219 Type.usize,
1023010220 .{ .immediate = array_len },
1023110221 );
......@@ -10235,20 +10225,21 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void {
1023510225}
1023610226
1023710227fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
10228 const mod = self.bin_file.options.module.?;
1023810229 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1023910230
10240 const src_ty = self.air.typeOf(ty_op.operand);
10241 const src_bits = @intCast(u32, src_ty.bitSize(self.target.*));
10231 const src_ty = self.typeOf(ty_op.operand);
10232 const src_bits = @intCast(u32, src_ty.bitSize(mod));
1024210233 const src_signedness =
10243 if (src_ty.isAbiInt()) src_ty.intInfo(self.target.*).signedness else .unsigned;
10244 const dst_ty = self.air.typeOfIndex(inst);
10234 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
10235 const dst_ty = self.typeOfIndex(inst);
1024510236
1024610237 const src_size = math.divCeil(u32, @max(switch (src_signedness) {
1024710238 .signed => src_bits,
1024810239 .unsigned => src_bits + 1,
1024910240 }, 32), 8) catch unreachable;
1025010241 if (src_size > 8) return self.fail("TODO implement airIntToFloat from {} to {}", .{
10251 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
10242 src_ty.fmt(mod), dst_ty.fmt(mod),
1025210243 });
1025310244
1025410245 const src_mcv = try self.resolveInst(ty_op.operand);
......@@ -10261,12 +10252,12 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
1026110252
1026210253 if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg);
1026310254
10264 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty));
10255 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));
1026510256 const dst_mcv = MCValue{ .register = dst_reg };
1026610257 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
1026710258 defer self.register_manager.unlockReg(dst_lock);
1026810259
10269 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag()) {
10260 const mir_tag = if (@as(?Mir.Inst.FixedTag, switch (dst_ty.zigTypeTag(mod)) {
1027010261 .Float => switch (dst_ty.floatBits(self.target.*)) {
1027110262 32 => if (self.hasFeature(.avx)) .{ .v_ss, .cvtsi2 } else .{ ._ss, .cvtsi2 },
1027210263 64 => if (self.hasFeature(.avx)) .{ .v_sd, .cvtsi2 } else .{ ._sd, .cvtsi2 },
......@@ -10275,7 +10266,7 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
1027510266 },
1027610267 else => null,
1027710268 })) |tag| tag else return self.fail("TODO implement airIntToFloat from {} to {}", .{
10278 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
10269 src_ty.fmt(mod), dst_ty.fmt(mod),
1027910270 });
1028010271 const dst_alias = dst_reg.to128();
1028110272 const src_alias = registerAlias(src_reg, src_size);
......@@ -10288,13 +10279,14 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) !void {
1028810279}
1028910280
1029010281fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
10282 const mod = self.bin_file.options.module.?;
1029110283 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1029210284
10293 const src_ty = self.air.typeOf(ty_op.operand);
10294 const dst_ty = self.air.typeOfIndex(inst);
10295 const dst_bits = @intCast(u32, dst_ty.bitSize(self.target.*));
10285 const src_ty = self.typeOf(ty_op.operand);
10286 const dst_ty = self.typeOfIndex(inst);
10287 const dst_bits = @intCast(u32, dst_ty.bitSize(mod));
1029610288 const dst_signedness =
10297 if (dst_ty.isAbiInt()) dst_ty.intInfo(self.target.*).signedness else .unsigned;
10289 if (dst_ty.isAbiInt(mod)) dst_ty.intInfo(mod).signedness else .unsigned;
1029810290
1029910291 const dst_size = math.divCeil(u32, @max(switch (dst_signedness) {
1030010292 .signed => dst_bits,
......@@ -10312,13 +10304,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
1031210304 const src_lock = self.register_manager.lockRegAssumeUnused(src_reg);
1031310305 defer self.register_manager.unlockReg(src_lock);
1031410306
10315 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty));
10307 const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod));
1031610308 const dst_mcv = MCValue{ .register = dst_reg };
1031710309 const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
1031810310 defer self.register_manager.unlockReg(dst_lock);
1031910311
1032010312 try self.asmRegisterRegister(
10321 if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag()) {
10313 if (@as(?Mir.Inst.FixedTag, switch (src_ty.zigTypeTag(mod)) {
1032210314 .Float => switch (src_ty.floatBits(self.target.*)) {
1032310315 32 => if (self.hasFeature(.avx)) .{ .v_, .cvttss2si } else .{ ._, .cvttss2si },
1032410316 64 => if (self.hasFeature(.avx)) .{ .v_, .cvttsd2si } else .{ ._, .cvttsd2si },
......@@ -10339,12 +10331,13 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) !void {
1033910331}
1034010332
1034110333fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void {
10334 const mod = self.bin_file.options.module.?;
1034210335 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1034310336 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
1034410337
10345 const ptr_ty = self.air.typeOf(extra.ptr);
10346 const val_ty = self.air.typeOf(extra.expected_value);
10347 const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*));
10338 const ptr_ty = self.typeOf(extra.ptr);
10339 const val_ty = self.typeOf(extra.expected_value);
10340 const val_abi_size = @intCast(u32, val_ty.abiSize(mod));
1034810341
1034910342 try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx });
1035010343 const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx });
......@@ -10433,6 +10426,7 @@ fn atomicOp(
1043310426 rmw_op: ?std.builtin.AtomicRmwOp,
1043410427 order: std.builtin.AtomicOrder,
1043510428) InnerError!MCValue {
10429 const mod = self.bin_file.options.module.?;
1043610430 const ptr_lock = switch (ptr_mcv) {
1043710431 .register => |reg| self.register_manager.lockReg(reg),
1043810432 else => null,
......@@ -10445,7 +10439,7 @@ fn atomicOp(
1044510439 };
1044610440 defer if (val_lock) |lock| self.register_manager.unlockReg(lock);
1044710441
10448 const val_abi_size = @intCast(u32, val_ty.abiSize(self.target.*));
10442 const val_abi_size = @intCast(u32, val_ty.abiSize(mod));
1044910443 const ptr_size = Memory.PtrSize.fromSize(val_abi_size);
1045010444 const ptr_mem = switch (ptr_mcv) {
1045110445 .immediate, .register, .register_offset, .lea_frame => ptr_mcv.deref().mem(ptr_size),
......@@ -10539,8 +10533,8 @@ fn atomicOp(
1053910533 .Or => try self.genBinOpMir(.{ ._, .@"or" }, val_ty, tmp_mcv, val_mcv),
1054010534 .Xor => try self.genBinOpMir(.{ ._, .xor }, val_ty, tmp_mcv, val_mcv),
1054110535 .Min, .Max => {
10542 const cc: Condition = switch (if (val_ty.isAbiInt())
10543 val_ty.intInfo(self.target.*).signedness
10536 const cc: Condition = switch (if (val_ty.isAbiInt(mod))
10537 val_ty.intInfo(mod).signedness
1054410538 else
1054510539 .unsigned) {
1054610540 .unsigned => switch (op) {
......@@ -10682,10 +10676,10 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {
1068210676
1068310677 const unused = self.liveness.isUnused(inst);
1068410678
10685 const ptr_ty = self.air.typeOf(pl_op.operand);
10679 const ptr_ty = self.typeOf(pl_op.operand);
1068610680 const ptr_mcv = try self.resolveInst(pl_op.operand);
1068710681
10688 const val_ty = self.air.typeOf(extra.operand);
10682 const val_ty = self.typeOf(extra.operand);
1068910683 const val_mcv = try self.resolveInst(extra.operand);
1069010684
1069110685 const result =
......@@ -10696,7 +10690,7 @@ fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void {
1069610690fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {
1069710691 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;
1069810692
10699 const ptr_ty = self.air.typeOf(atomic_load.ptr);
10693 const ptr_ty = self.typeOf(atomic_load.ptr);
1070010694 const ptr_mcv = try self.resolveInst(atomic_load.ptr);
1070110695 const ptr_lock = switch (ptr_mcv) {
1070210696 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
......@@ -10717,10 +10711,10 @@ fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void {
1071710711fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOrder) !void {
1071810712 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1071910713
10720 const ptr_ty = self.air.typeOf(bin_op.lhs);
10714 const ptr_ty = self.typeOf(bin_op.lhs);
1072110715 const ptr_mcv = try self.resolveInst(bin_op.lhs);
1072210716
10723 const val_ty = self.air.typeOf(bin_op.rhs);
10717 const val_ty = self.typeOf(bin_op.rhs);
1072410718 const val_mcv = try self.resolveInst(bin_op.rhs);
1072510719
1072610720 const result = try self.atomicOp(ptr_mcv, val_mcv, ptr_ty, val_ty, true, null, order);
......@@ -10728,6 +10722,7 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr
1072810722}
1072910723
1073010724fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
10725 const mod = self.bin_file.options.module.?;
1073110726 if (safety) {
1073210727 // TODO if the value is undef, write 0xaa bytes to dest
1073310728 } else {
......@@ -10737,7 +10732,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1073710732 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1073810733
1073910734 const dst_ptr = try self.resolveInst(bin_op.lhs);
10740 const dst_ptr_ty = self.air.typeOf(bin_op.lhs);
10735 const dst_ptr_ty = self.typeOf(bin_op.lhs);
1074110736 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
1074210737 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1074310738 else => null,
......@@ -10745,26 +10740,26 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1074510740 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
1074610741
1074710742 const src_val = try self.resolveInst(bin_op.rhs);
10748 const elem_ty = self.air.typeOf(bin_op.rhs);
10743 const elem_ty = self.typeOf(bin_op.rhs);
1074910744 const src_val_lock: ?RegisterLock = switch (src_val) {
1075010745 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1075110746 else => null,
1075210747 };
1075310748 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);
1075410749
10755 const elem_abi_size = @intCast(u31, elem_ty.abiSize(self.target.*));
10750 const elem_abi_size = @intCast(u31, elem_ty.abiSize(mod));
1075610751
1075710752 if (elem_abi_size == 1) {
10758 const ptr: MCValue = switch (dst_ptr_ty.ptrSize()) {
10753 const ptr: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
1075910754 // TODO: this only handles slices stored in the stack
1076010755 .Slice => dst_ptr,
1076110756 .One => dst_ptr,
1076210757 .C, .Many => unreachable,
1076310758 };
10764 const len: MCValue = switch (dst_ptr_ty.ptrSize()) {
10759 const len: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
1076510760 // TODO: this only handles slices stored in the stack
1076610761 .Slice => dst_ptr.address().offset(8).deref(),
10767 .One => .{ .immediate = dst_ptr_ty.childType().arrayLen() },
10762 .One => .{ .immediate = dst_ptr_ty.childType(mod).arrayLen(mod) },
1076810763 .C, .Many => unreachable,
1076910764 };
1077010765 const len_lock: ?RegisterLock = switch (len) {
......@@ -10780,10 +10775,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1078010775 // Store the first element, and then rely on memcpy copying forwards.
1078110776 // Length zero requires a runtime check - so we handle arrays specially
1078210777 // here to elide it.
10783 switch (dst_ptr_ty.ptrSize()) {
10778 switch (dst_ptr_ty.ptrSize(mod)) {
1078410779 .Slice => {
10785 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
10786 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(&buf);
10780 const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(mod);
1078710781
1078810782 // TODO: this only handles slices stored in the stack
1078910783 const ptr = dst_ptr;
......@@ -10823,13 +10817,9 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1082310817 try self.performReloc(skip_reloc);
1082410818 },
1082510819 .One => {
10826 var elem_ptr_pl = Type.Payload.ElemType{
10827 .base = .{ .tag = .single_mut_pointer },
10828 .data = elem_ty,
10829 };
10830 const elem_ptr_ty = Type.initPayload(&elem_ptr_pl.base);
10820 const elem_ptr_ty = try mod.singleMutPtrType(elem_ty);
1083110821
10832 const len = dst_ptr_ty.childType().arrayLen();
10822 const len = dst_ptr_ty.childType(mod).arrayLen(mod);
1083310823
1083410824 assert(len != 0); // prevented by Sema
1083510825 try self.store(elem_ptr_ty, dst_ptr, src_val);
......@@ -10854,10 +10844,11 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void {
1085410844}
1085510845
1085610846fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
10847 const mod = self.bin_file.options.module.?;
1085710848 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
1085810849
1085910850 const dst_ptr = try self.resolveInst(bin_op.lhs);
10860 const dst_ptr_ty = self.air.typeOf(bin_op.lhs);
10851 const dst_ptr_ty = self.typeOf(bin_op.lhs);
1086110852 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
1086210853 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1086310854 else => null,
......@@ -10871,9 +10862,9 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
1087110862 };
1087210863 defer if (src_ptr_lock) |lock| self.register_manager.unlockReg(lock);
1087310864
10874 const len: MCValue = switch (dst_ptr_ty.ptrSize()) {
10865 const len: MCValue = switch (dst_ptr_ty.ptrSize(mod)) {
1087510866 .Slice => dst_ptr.address().offset(8).deref(),
10876 .One => .{ .immediate = dst_ptr_ty.childType().arrayLen() },
10867 .One => .{ .immediate = dst_ptr_ty.childType(mod).arrayLen(mod) },
1087710868 .C, .Many => unreachable,
1087810869 };
1087910870 const len_lock: ?RegisterLock = switch (len) {
......@@ -10891,14 +10882,14 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
1089110882fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
1089210883 const mod = self.bin_file.options.module.?;
1089310884 const un_op = self.air.instructions.items(.data)[inst].un_op;
10894 const inst_ty = self.air.typeOfIndex(inst);
10895 const enum_ty = self.air.typeOf(un_op);
10885 const inst_ty = self.typeOfIndex(inst);
10886 const enum_ty = self.typeOf(un_op);
1089610887
1089710888 // We need a properly aligned and sized call frame to be able to call this function.
1089810889 {
1089910890 const needed_call_frame = FrameAlloc.init(.{
10900 .size = inst_ty.abiSize(self.target.*),
10901 .alignment = inst_ty.abiAlignment(self.target.*),
10891 .size = inst_ty.abiSize(mod),
10892 .alignment = inst_ty.abiAlignment(mod),
1090210893 });
1090310894 const frame_allocs_slice = self.frame_allocs.slice();
1090410895 const stack_frame_size =
......@@ -10923,7 +10914,7 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
1092310914 try self.genLazySymbolRef(
1092410915 .call,
1092510916 .rax,
10926 link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod),
10917 link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(mod), mod),
1092710918 );
1092810919
1092910920 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
......@@ -10933,7 +10924,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
1093310924 const mod = self.bin_file.options.module.?;
1093410925 const un_op = self.air.instructions.items(.data)[inst].un_op;
1093510926
10936 const err_ty = self.air.typeOf(un_op);
10927 const err_ty = self.typeOf(un_op);
1093710928 const err_mcv = try self.resolveInst(un_op);
1093810929 const err_reg = try self.copyToTmpRegister(err_ty, err_mcv);
1093910930 const err_lock = self.register_manager.lockRegAssumeUnused(err_reg);
......@@ -11013,17 +11004,18 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
1101311004}
1101411005
1101511006fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
11007 const mod = self.bin_file.options.module.?;
1101611008 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
11017 const vector_ty = self.air.typeOfIndex(inst);
11018 const dst_rc = regClassForType(vector_ty);
11019 const scalar_ty = vector_ty.scalarType();
11009 const vector_ty = self.typeOfIndex(inst);
11010 const dst_rc = regClassForType(vector_ty, mod);
11011 const scalar_ty = vector_ty.scalarType(mod);
1102011012
1102111013 const src_mcv = try self.resolveInst(ty_op.operand);
1102211014 const result: MCValue = result: {
11023 switch (scalar_ty.zigTypeTag()) {
11015 switch (scalar_ty.zigTypeTag(mod)) {
1102411016 else => {},
1102511017 .Float => switch (scalar_ty.floatBits(self.target.*)) {
11026 32 => switch (vector_ty.vectorLen()) {
11018 32 => switch (vector_ty.vectorLen(mod)) {
1102711019 1 => {
1102811020 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1102911021 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
......@@ -11103,7 +11095,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1110311095 },
1110411096 else => {},
1110511097 },
11106 64 => switch (vector_ty.vectorLen()) {
11098 64 => switch (vector_ty.vectorLen(mod)) {
1110711099 1 => {
1110811100 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1110911101 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
......@@ -11169,7 +11161,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void {
1116911161 },
1117011162 else => {},
1117111163 },
11172 128 => switch (vector_ty.vectorLen()) {
11164 128 => switch (vector_ty.vectorLen(mod)) {
1117311165 1 => {
1117411166 if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) break :result src_mcv;
1117511167 const dst_reg = try self.register_manager.allocReg(inst, dst_rc);
......@@ -11233,36 +11225,37 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void {
1123311225}
1123411226
1123511227fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
11236 const result_ty = self.air.typeOfIndex(inst);
11237 const len = @intCast(usize, result_ty.arrayLen());
11228 const mod = self.bin_file.options.module.?;
11229 const result_ty = self.typeOfIndex(inst);
11230 const len = @intCast(usize, result_ty.arrayLen(mod));
1123811231 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1123911232 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
1124011233 const result: MCValue = result: {
11241 switch (result_ty.zigTypeTag()) {
11234 switch (result_ty.zigTypeTag(mod)) {
1124211235 .Struct => {
1124311236 const frame_index =
11244 try self.allocFrameIndex(FrameAlloc.initType(result_ty, self.target.*));
11245 if (result_ty.containerLayout() == .Packed) {
11246 const struct_obj = result_ty.castTag(.@"struct").?.data;
11237 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
11238 if (result_ty.containerLayout(mod) == .Packed) {
11239 const struct_obj = mod.typeToStruct(result_ty).?;
1124711240 try self.genInlineMemset(
1124811241 .{ .lea_frame = .{ .index = frame_index } },
1124911242 .{ .immediate = 0 },
11250 .{ .immediate = result_ty.abiSize(self.target.*) },
11243 .{ .immediate = result_ty.abiSize(mod) },
1125111244 );
1125211245 for (elements, 0..) |elem, elem_i| {
11253 if (result_ty.structFieldValueComptime(elem_i) != null) continue;
11246 if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;
1125411247
11255 const elem_ty = result_ty.structFieldType(elem_i);
11256 const elem_bit_size = @intCast(u32, elem_ty.bitSize(self.target.*));
11248 const elem_ty = result_ty.structFieldType(elem_i, mod);
11249 const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));
1125711250 if (elem_bit_size > 64) {
1125811251 return self.fail(
1125911252 "TODO airAggregateInit implement packed structs with large fields",
1126011253 .{},
1126111254 );
1126211255 }
11263 const elem_abi_size = @intCast(u32, elem_ty.abiSize(self.target.*));
11256 const elem_abi_size = @intCast(u32, elem_ty.abiSize(mod));
1126411257 const elem_abi_bits = elem_abi_size * 8;
11265 const elem_off = struct_obj.packedFieldBitOffset(self.target.*, elem_i);
11258 const elem_off = struct_obj.packedFieldBitOffset(mod, elem_i);
1126611259 const elem_byte_off = @intCast(i32, elem_off / elem_abi_bits * elem_abi_size);
1126711260 const elem_bit_off = elem_off % elem_abi_bits;
1126811261 const elem_mcv = try self.resolveInst(elem);
......@@ -11322,10 +11315,10 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1132211315 }
1132311316 }
1132411317 } else for (elements, 0..) |elem, elem_i| {
11325 if (result_ty.structFieldValueComptime(elem_i) != null) continue;
11318 if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;
1132611319
11327 const elem_ty = result_ty.structFieldType(elem_i);
11328 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, self.target.*));
11320 const elem_ty = result_ty.structFieldType(elem_i, mod);
11321 const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));
1132911322 const elem_mcv = try self.resolveInst(elem);
1133011323 const mat_elem_mcv = switch (elem_mcv) {
1133111324 .load_tlv => |sym_index| MCValue{ .lea_tlv = sym_index },
......@@ -11337,9 +11330,9 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1133711330 },
1133811331 .Array => {
1133911332 const frame_index =
11340 try self.allocFrameIndex(FrameAlloc.initType(result_ty, self.target.*));
11341 const elem_ty = result_ty.childType();
11342 const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
11333 try self.allocFrameIndex(FrameAlloc.initType(result_ty, mod));
11334 const elem_ty = result_ty.childType(mod);
11335 const elem_size = @intCast(u32, elem_ty.abiSize(mod));
1134311336
1134411337 for (elements, 0..) |elem, elem_i| {
1134511338 const elem_mcv = try self.resolveInst(elem);
......@@ -11350,7 +11343,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1135011343 const elem_off = @intCast(i32, elem_size * elem_i);
1135111344 try self.genSetMem(.{ .frame = frame_index }, elem_off, elem_ty, mat_elem_mcv);
1135211345 }
11353 if (result_ty.sentinel()) |sentinel| try self.genSetMem(
11346 if (result_ty.sentinel(mod)) |sentinel| try self.genSetMem(
1135411347 .{ .frame = frame_index },
1135511348 @intCast(i32, elem_size * elements.len),
1135611349 elem_ty,
......@@ -11374,13 +11367,14 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
1137411367}
1137511368
1137611369fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
11370 const mod = self.bin_file.options.module.?;
1137711371 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1137811372 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
1137911373 const result: MCValue = result: {
11380 const union_ty = self.air.typeOfIndex(inst);
11381 const layout = union_ty.unionGetLayout(self.target.*);
11374 const union_ty = self.typeOfIndex(inst);
11375 const layout = union_ty.unionGetLayout(mod);
1138211376
11383 const src_ty = self.air.typeOf(extra.init);
11377 const src_ty = self.typeOf(extra.init);
1138411378 const src_mcv = try self.resolveInst(extra.init);
1138511379 if (layout.tag_size == 0) {
1138611380 if (self.reuseOperand(inst, extra.init, 0, src_mcv)) break :result src_mcv;
......@@ -11392,15 +11386,13 @@ fn airUnionInit(self: *Self, inst: Air.Inst.Index) !void {
1139211386
1139311387 const dst_mcv = try self.allocRegOrMem(inst, false);
1139411388
11395 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
11389 const union_obj = mod.typeToUnion(union_ty).?;
1139611390 const field_name = union_obj.fields.keys()[extra.field_index];
11397 const tag_ty = union_ty.unionTagTypeSafety().?;
11398 const field_index = @intCast(u32, tag_ty.enumFieldIndex(field_name).?);
11399 var tag_pl = Value.Payload.U32{ .base = .{ .tag = .enum_field_index }, .data = field_index };
11400 const tag_val = Value.initPayload(&tag_pl.base);
11401 var tag_int_pl: Value.Payload.U64 = undefined;
11402 const tag_int_val = tag_val.enumToInt(tag_ty, &tag_int_pl);
11403 const tag_int = tag_int_val.toUnsignedInt(self.target.*);
11391 const tag_ty = union_obj.tag_ty;
11392 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
11393 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
11394 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);
11395 const tag_int = tag_int_val.toUnsignedInt(mod);
1140411396 const tag_off = if (layout.tag_align < layout.payload_align)
1140511397 @intCast(i32, layout.payload_size)
1140611398 else
......@@ -11424,9 +11416,10 @@ fn airPrefetch(self: *Self, inst: Air.Inst.Index) !void {
1142411416}
1142511417
1142611418fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
11419 const mod = self.bin_file.options.module.?;
1142711420 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1142811421 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
11429 const ty = self.air.typeOfIndex(inst);
11422 const ty = self.typeOfIndex(inst);
1143011423
1143111424 if (!self.hasFeature(.fma)) return self.fail("TODO implement airMulAdd for {}", .{
1143211425 ty.fmt(self.bin_file.options.module.?),
......@@ -11466,21 +11459,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1146611459 const mir_tag = if (@as(
1146711460 ?Mir.Inst.FixedTag,
1146811461 if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 }))
11469 switch (ty.zigTypeTag()) {
11462 switch (ty.zigTypeTag(mod)) {
1147011463 .Float => switch (ty.floatBits(self.target.*)) {
1147111464 32 => .{ .v_ss, .fmadd132 },
1147211465 64 => .{ .v_sd, .fmadd132 },
1147311466 16, 80, 128 => null,
1147411467 else => unreachable,
1147511468 },
11476 .Vector => switch (ty.childType().zigTypeTag()) {
11477 .Float => switch (ty.childType().floatBits(self.target.*)) {
11478 32 => switch (ty.vectorLen()) {
11469 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11470 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11471 32 => switch (ty.vectorLen(mod)) {
1147911472 1 => .{ .v_ss, .fmadd132 },
1148011473 2...8 => .{ .v_ps, .fmadd132 },
1148111474 else => null,
1148211475 },
11483 64 => switch (ty.vectorLen()) {
11476 64 => switch (ty.vectorLen(mod)) {
1148411477 1 => .{ .v_sd, .fmadd132 },
1148511478 2...4 => .{ .v_pd, .fmadd132 },
1148611479 else => null,
......@@ -11493,21 +11486,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1149311486 else => unreachable,
1149411487 }
1149511488 else if (mem.eql(u2, &order, &.{ 2, 1, 3 }) or mem.eql(u2, &order, &.{ 1, 2, 3 }))
11496 switch (ty.zigTypeTag()) {
11489 switch (ty.zigTypeTag(mod)) {
1149711490 .Float => switch (ty.floatBits(self.target.*)) {
1149811491 32 => .{ .v_ss, .fmadd213 },
1149911492 64 => .{ .v_sd, .fmadd213 },
1150011493 16, 80, 128 => null,
1150111494 else => unreachable,
1150211495 },
11503 .Vector => switch (ty.childType().zigTypeTag()) {
11504 .Float => switch (ty.childType().floatBits(self.target.*)) {
11505 32 => switch (ty.vectorLen()) {
11496 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11497 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11498 32 => switch (ty.vectorLen(mod)) {
1150611499 1 => .{ .v_ss, .fmadd213 },
1150711500 2...8 => .{ .v_ps, .fmadd213 },
1150811501 else => null,
1150911502 },
11510 64 => switch (ty.vectorLen()) {
11503 64 => switch (ty.vectorLen(mod)) {
1151111504 1 => .{ .v_sd, .fmadd213 },
1151211505 2...4 => .{ .v_pd, .fmadd213 },
1151311506 else => null,
......@@ -11520,21 +11513,21 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1152011513 else => unreachable,
1152111514 }
1152211515 else if (mem.eql(u2, &order, &.{ 2, 3, 1 }) or mem.eql(u2, &order, &.{ 3, 2, 1 }))
11523 switch (ty.zigTypeTag()) {
11516 switch (ty.zigTypeTag(mod)) {
1152411517 .Float => switch (ty.floatBits(self.target.*)) {
1152511518 32 => .{ .v_ss, .fmadd231 },
1152611519 64 => .{ .v_sd, .fmadd231 },
1152711520 16, 80, 128 => null,
1152811521 else => unreachable,
1152911522 },
11530 .Vector => switch (ty.childType().zigTypeTag()) {
11531 .Float => switch (ty.childType().floatBits(self.target.*)) {
11532 32 => switch (ty.vectorLen()) {
11523 .Vector => switch (ty.childType(mod).zigTypeTag(mod)) {
11524 .Float => switch (ty.childType(mod).floatBits(self.target.*)) {
11525 32 => switch (ty.vectorLen(mod)) {
1153311526 1 => .{ .v_ss, .fmadd231 },
1153411527 2...8 => .{ .v_ps, .fmadd231 },
1153511528 else => null,
1153611529 },
11537 64 => switch (ty.vectorLen()) {
11530 64 => switch (ty.vectorLen(mod)) {
1153811531 1 => .{ .v_sd, .fmadd231 },
1153911532 2...4 => .{ .v_pd, .fmadd231 },
1154011533 else => null,
......@@ -11555,7 +11548,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1155511548 var mops: [3]MCValue = undefined;
1155611549 for (order, mcvs) |mop_index, mcv| mops[mop_index - 1] = mcv;
1155711550
11558 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
11551 const abi_size = @intCast(u32, ty.abiSize(mod));
1155911552 const mop1_reg = registerAlias(mops[0].getReg().?, abi_size);
1156011553 const mop2_reg = registerAlias(mops[1].getReg().?, abi_size);
1156111554 if (mops[2].isRegister()) try self.asmRegisterRegisterRegister(
......@@ -11573,22 +11566,22 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
1157311566}
1157411567
1157511568fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
11576 const ty = self.air.typeOf(ref);
11569 const mod = self.bin_file.options.module.?;
11570 const ty = self.typeOf(ref);
1157711571
1157811572 // If the type has no codegen bits, no need to store it.
11579 if (!ty.hasRuntimeBitsIgnoreComptime()) return .none;
11573 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return .none;
1158011574
1158111575 if (Air.refToIndex(ref)) |inst| {
1158211576 const mcv = switch (self.air.instructions.items(.tag)[inst]) {
11583 .constant => tracking: {
11577 .interned => tracking: {
1158411578 const gop = try self.const_tracking.getOrPut(self.gpa, inst);
1158511579 if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
1158611580 .ty = ty,
11587 .val = self.air.value(ref).?,
11581 .val = self.air.instructions.items(.data)[inst].interned.toValue(),
1158811582 }));
1158911583 break :tracking gop.value_ptr;
1159011584 },
11591 .const_ty => unreachable,
1159211585 else => self.inst_tracking.getPtr(inst).?,
1159311586 }.short;
1159411587 switch (mcv) {
......@@ -11597,13 +11590,12 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
1159711590 }
1159811591 }
1159911592
11600 return self.genTypedValue(.{ .ty = ty, .val = self.air.value(ref).? });
11593 return self.genTypedValue(.{ .ty = ty, .val = (try self.air.value(ref, mod)).? });
1160111594}
1160211595
1160311596fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {
1160411597 const tracking = switch (self.air.instructions.items(.tag)[inst]) {
11605 .constant => &self.const_tracking,
11606 .const_ty => unreachable,
11598 .interned => &self.const_tracking,
1160711599 else => &self.inst_tracking,
1160811600 }.getPtr(inst).?;
1160911601 return switch (tracking.short) {
......@@ -11634,7 +11626,8 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
1163411626}
1163511627
1163611628fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
11637 return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl())) {
11629 const mod = self.bin_file.options.module.?;
11630 return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl(mod))) {
1163811631 .mcv => |mcv| switch (mcv) {
1163911632 .none => .none,
1164011633 .undef => .undef,
......@@ -11666,17 +11659,23 @@ const CallMCValues = struct {
1166611659/// Caller must call `CallMCValues.deinit`.
1166711660fn resolveCallingConventionValues(
1166811661 self: *Self,
11669 fn_ty: Type,
11662 fn_info: InternPool.Key.FuncType,
1167011663 var_args: []const Air.Inst.Ref,
1167111664 stack_frame_base: FrameIndex,
1167211665) !CallMCValues {
11673 const cc = fn_ty.fnCallingConvention();
11674 const param_len = fn_ty.fnParamLen();
11675 const param_types = try self.gpa.alloc(Type, param_len + var_args.len);
11666 const mod = self.bin_file.options.module.?;
11667 const cc = fn_info.cc;
11668 const param_types = try self.gpa.alloc(Type, fn_info.param_types.len + var_args.len);
1167611669 defer self.gpa.free(param_types);
11677 fn_ty.fnParamTypes(param_types);
11670
11671 for (param_types[0..fn_info.param_types.len], fn_info.param_types) |*dest, src| {
11672 dest.* = src.toType();
11673 }
1167811674 // TODO: promote var arg types
11679 for (param_types[param_len..], var_args) |*param_ty, arg| param_ty.* = self.air.typeOf(arg);
11675 for (param_types[fn_info.param_types.len..], var_args) |*param_ty, arg| {
11676 param_ty.* = self.typeOf(arg);
11677 }
11678
1168011679 var result: CallMCValues = .{
1168111680 .args = try self.gpa.alloc(MCValue, param_types.len),
1168211681 // These undefined values must be populated before returning from this function.
......@@ -11686,7 +11685,7 @@ fn resolveCallingConventionValues(
1168611685 };
1168711686 errdefer self.gpa.free(result.args);
1168811687
11689 const ret_ty = fn_ty.fnReturnType();
11688 const ret_ty = fn_info.return_type.toType();
1169011689
1169111690 switch (cc) {
1169211691 .Naked => {
......@@ -11702,21 +11701,21 @@ fn resolveCallingConventionValues(
1170211701 switch (self.target.os.tag) {
1170311702 .windows => {
1170411703 // Align the stack to 16bytes before allocating shadow stack space (if any).
11705 result.stack_byte_count += @intCast(u31, 4 * Type.usize.abiSize(self.target.*));
11704 result.stack_byte_count += @intCast(u31, 4 * Type.usize.abiSize(mod));
1170611705 },
1170711706 else => {},
1170811707 }
1170911708
1171011709 // Return values
11711 if (ret_ty.zigTypeTag() == .NoReturn) {
11710 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
1171211711 result.return_value = InstTracking.init(.unreach);
11713 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
11712 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1171411713 // TODO: is this even possible for C calling convention?
1171511714 result.return_value = InstTracking.init(.none);
1171611715 } else {
1171711716 const classes = switch (self.target.os.tag) {
11718 .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, self.target.*)},
11719 else => mem.sliceTo(&abi.classifySystemV(ret_ty, self.target.*, .ret), .none),
11717 .windows => &[1]abi.Class{abi.classifyWindows(ret_ty, mod)},
11718 else => mem.sliceTo(&abi.classifySystemV(ret_ty, mod, .ret), .none),
1172011719 };
1172111720 if (classes.len > 1) {
1172211721 return self.fail("TODO handle multiple classes per type", .{});
......@@ -11725,7 +11724,7 @@ fn resolveCallingConventionValues(
1172511724 result.return_value = switch (classes[0]) {
1172611725 .integer => InstTracking.init(.{ .register = registerAlias(
1172711726 ret_reg,
11728 @intCast(u32, ret_ty.abiSize(self.target.*)),
11727 @intCast(u32, ret_ty.abiSize(mod)),
1172911728 ) }),
1173011729 .float, .sse => InstTracking.init(.{ .register = .xmm0 }),
1173111730 .memory => ret: {
......@@ -11744,11 +11743,11 @@ fn resolveCallingConventionValues(
1174411743
1174511744 // Input params
1174611745 for (param_types, result.args) |ty, *arg| {
11747 assert(ty.hasRuntimeBitsIgnoreComptime());
11746 assert(ty.hasRuntimeBitsIgnoreComptime(mod));
1174811747
1174911748 const classes = switch (self.target.os.tag) {
11750 .windows => &[1]abi.Class{abi.classifyWindows(ty, self.target.*)},
11751 else => mem.sliceTo(&abi.classifySystemV(ty, self.target.*, .arg), .none),
11749 .windows => &[1]abi.Class{abi.classifyWindows(ty, mod)},
11750 else => mem.sliceTo(&abi.classifySystemV(ty, mod, .arg), .none),
1175211751 };
1175311752 if (classes.len > 1) {
1175411753 return self.fail("TODO handle multiple classes per type", .{});
......@@ -11783,8 +11782,8 @@ fn resolveCallingConventionValues(
1178311782 }),
1178411783 }
1178511784
11786 const param_size = @intCast(u31, ty.abiSize(self.target.*));
11787 const param_align = @intCast(u31, ty.abiAlignment(self.target.*));
11785 const param_size = @intCast(u31, ty.abiSize(mod));
11786 const param_align = @intCast(u31, ty.abiAlignment(mod));
1178811787 result.stack_byte_count =
1178911788 mem.alignForwardGeneric(u31, result.stack_byte_count, param_align);
1179011789 arg.* = .{ .load_frame = .{
......@@ -11798,13 +11797,13 @@ fn resolveCallingConventionValues(
1179811797 result.stack_align = 16;
1179911798
1180011799 // Return values
11801 if (ret_ty.zigTypeTag() == .NoReturn) {
11800 if (ret_ty.zigTypeTag(mod) == .NoReturn) {
1180211801 result.return_value = InstTracking.init(.unreach);
11803 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
11802 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1180411803 result.return_value = InstTracking.init(.none);
1180511804 } else {
1180611805 const ret_reg = abi.getCAbiIntReturnRegs(self.target.*)[0];
11807 const ret_ty_size = @intCast(u31, ret_ty.abiSize(self.target.*));
11806 const ret_ty_size = @intCast(u31, ret_ty.abiSize(mod));
1180811807 if (ret_ty_size <= 8 and !ret_ty.isRuntimeFloat()) {
1180911808 const aliased_reg = registerAlias(ret_reg, ret_ty_size);
1181011809 result.return_value = .{ .short = .{ .register = aliased_reg }, .long = .none };
......@@ -11819,12 +11818,12 @@ fn resolveCallingConventionValues(
1181911818
1182011819 // Input params
1182111820 for (param_types, result.args) |ty, *arg| {
11822 if (!ty.hasRuntimeBitsIgnoreComptime()) {
11821 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
1182311822 arg.* = .none;
1182411823 continue;
1182511824 }
11826 const param_size = @intCast(u31, ty.abiSize(self.target.*));
11827 const param_align = @intCast(u31, ty.abiAlignment(self.target.*));
11825 const param_size = @intCast(u31, ty.abiSize(mod));
11826 const param_align = @intCast(u31, ty.abiAlignment(mod));
1182811827 result.stack_byte_count =
1182911828 mem.alignForwardGeneric(u31, result.stack_byte_count, param_align);
1183011829 arg.* = .{ .load_frame = .{
......@@ -11908,9 +11907,10 @@ fn registerAlias(reg: Register, size_bytes: u32) Register {
1190811907/// Truncates the value in the register in place.
1190911908/// Clobbers any remaining bits.
1191011909fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
11911 const int_info = if (ty.isAbiInt()) ty.intInfo(self.target.*) else std.builtin.Type.Int{
11910 const mod = self.bin_file.options.module.?;
11911 const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{
1191211912 .signedness = .unsigned,
11913 .bits = @intCast(u16, ty.bitSize(self.target.*)),
11913 .bits = @intCast(u16, ty.bitSize(mod)),
1191411914 };
1191511915 const max_reg_bit_width = Register.rax.bitSize();
1191611916 switch (int_info.signedness) {
......@@ -11953,8 +11953,9 @@ fn truncateRegister(self: *Self, ty: Type, reg: Register) !void {
1195311953}
1195411954
1195511955fn regBitSize(self: *Self, ty: Type) u64 {
11956 const abi_size = ty.abiSize(self.target.*);
11957 return switch (ty.zigTypeTag()) {
11956 const mod = self.bin_file.options.module.?;
11957 const abi_size = ty.abiSize(mod);
11958 return switch (ty.zigTypeTag(mod)) {
1195811959 else => switch (abi_size) {
1195911960 1 => 8,
1196011961 2 => 16,
......@@ -11971,7 +11972,8 @@ fn regBitSize(self: *Self, ty: Type) u64 {
1197111972}
1197211973
1197311974fn regExtraBits(self: *Self, ty: Type) u64 {
11974 return self.regBitSize(ty) - ty.bitSize(self.target.*);
11975 const mod = self.bin_file.options.module.?;
11976 return self.regBitSize(ty) - ty.bitSize(mod);
1197511977}
1197611978
1197711979fn hasFeature(self: *Self, feature: Target.x86.Feature) bool {
......@@ -11983,3 +11985,13 @@ fn hasAnyFeatures(self: *Self, features: anytype) bool {
1198311985fn hasAllFeatures(self: *Self, features: anytype) bool {
1198411986 return Target.x86.featureSetHasAll(self.target.cpu.features, features);
1198511987}
11988
11989fn typeOf(self: *Self, inst: Air.Inst.Ref) Type {
11990 const mod = self.bin_file.options.module.?;
11991 return self.air.typeOf(inst, &mod.intern_pool);
11992}
11993
11994fn typeOfIndex(self: *Self, inst: Air.Inst.Index) Type {
11995 const mod = self.bin_file.options.module.?;
11996 return self.air.typeOfIndex(inst, &mod.intern_pool);
11997}
src/arch/x86_64/abi.zig+33-63
......@@ -1,10 +1,3 @@
1const std = @import("std");
2const Type = @import("../../type.zig").Type;
3const Target = std.Target;
4const assert = std.debug.assert;
5const Register = @import("bits.zig").Register;
6const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
7
81pub const Class = enum {
92 integer,
103 sse,
......@@ -19,7 +12,7 @@ pub const Class = enum {
1912 float_combine,
2013};
2114
22pub fn classifyWindows(ty: Type, target: Target) Class {
15pub fn classifyWindows(ty: Type, mod: *Module) Class {
2316 // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017
2417 // "There's a strict one-to-one correspondence between a function call's arguments
2518 // and the registers used for those arguments. Any argument that doesn't fit in 8
......@@ -28,7 +21,7 @@ pub fn classifyWindows(ty: Type, target: Target) Class {
2821 // "All floating point operations are done using the 16 XMM registers."
2922 // "Structs and unions of size 8, 16, 32, or 64 bits, and __m64 types, are passed
3023 // as if they were integers of the same size."
31 switch (ty.zigTypeTag()) {
24 switch (ty.zigTypeTag(mod)) {
3225 .Pointer,
3326 .Int,
3427 .Bool,
......@@ -43,12 +36,12 @@ pub fn classifyWindows(ty: Type, target: Target) Class {
4336 .ErrorUnion,
4437 .AnyFrame,
4538 .Frame,
46 => switch (ty.abiSize(target)) {
39 => switch (ty.abiSize(mod)) {
4740 0 => unreachable,
4841 1, 2, 4, 8 => return .integer,
49 else => switch (ty.zigTypeTag()) {
42 else => switch (ty.zigTypeTag(mod)) {
5043 .Int => return .win_i128,
51 .Struct, .Union => if (ty.containerLayout() == .Packed) {
44 .Struct, .Union => if (ty.containerLayout(mod) == .Packed) {
5245 return .win_i128;
5346 } else {
5447 return .memory;
......@@ -75,14 +68,15 @@ pub const Context = enum { ret, arg, other };
7568
7669/// There are a maximum of 8 possible return slots. Returned values are in
7770/// the beginning of the array; unused slots are filled with .none.
78pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
71pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class {
72 const target = mod.getTarget();
7973 const memory_class = [_]Class{
8074 .memory, .none, .none, .none,
8175 .none, .none, .none, .none,
8276 };
8377 var result = [1]Class{.none} ** 8;
84 switch (ty.zigTypeTag()) {
85 .Pointer => switch (ty.ptrSize()) {
78 switch (ty.zigTypeTag(mod)) {
79 .Pointer => switch (ty.ptrSize(mod)) {
8680 .Slice => {
8781 result[0] = .integer;
8882 result[1] = .integer;
......@@ -94,7 +88,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
9488 },
9589 },
9690 .Int, .Enum, .ErrorSet => {
97 const bits = ty.intInfo(target).bits;
91 const bits = ty.intInfo(mod).bits;
9892 if (bits <= 64) {
9993 result[0] = .integer;
10094 return result;
......@@ -164,8 +158,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
164158 else => unreachable,
165159 },
166160 .Vector => {
167 const elem_ty = ty.childType();
168 const bits = elem_ty.bitSize(target) * ty.arrayLen();
161 const elem_ty = ty.childType(mod);
162 const bits = elem_ty.bitSize(mod) * ty.arrayLen(mod);
169163 if (bits <= 64) return .{
170164 .sse, .none, .none, .none,
171165 .none, .none, .none, .none,
......@@ -204,7 +198,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
204198 return memory_class;
205199 },
206200 .Optional => {
207 if (ty.isPtrLikeOptional()) {
201 if (ty.isPtrLikeOptional(mod)) {
208202 result[0] = .integer;
209203 return result;
210204 }
......@@ -215,8 +209,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
215209 // it contains unaligned fields, it has class MEMORY"
216210 // "If the size of the aggregate exceeds a single eightbyte, each is classified
217211 // separately.".
218 const ty_size = ty.abiSize(target);
219 if (ty.containerLayout() == .Packed) {
212 const ty_size = ty.abiSize(mod);
213 if (ty.containerLayout(mod) == .Packed) {
220214 assert(ty_size <= 128);
221215 result[0] = .integer;
222216 if (ty_size > 64) result[1] = .integer;
......@@ -227,15 +221,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
227221
228222 var result_i: usize = 0; // out of 8
229223 var byte_i: usize = 0; // out of 8
230 const fields = ty.structFields();
224 const fields = ty.structFields(mod);
231225 for (fields.values()) |field| {
232226 if (field.abi_align != 0) {
233 if (field.abi_align < field.ty.abiAlignment(target)) {
227 if (field.abi_align < field.ty.abiAlignment(mod)) {
234228 return memory_class;
235229 }
236230 }
237 const field_size = field.ty.abiSize(target);
238 const field_class_array = classifySystemV(field.ty, target, .other);
231 const field_size = field.ty.abiSize(mod);
232 const field_class_array = classifySystemV(field.ty, mod, .other);
239233 const field_class = std.mem.sliceTo(&field_class_array, .none);
240234 if (byte_i + field_size <= 8) {
241235 // Combine this field with the previous one.
......@@ -334,8 +328,8 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
334328 // it contains unaligned fields, it has class MEMORY"
335329 // "If the size of the aggregate exceeds a single eightbyte, each is classified
336330 // separately.".
337 const ty_size = ty.abiSize(target);
338 if (ty.containerLayout() == .Packed) {
331 const ty_size = ty.abiSize(mod);
332 if (ty.containerLayout(mod) == .Packed) {
339333 assert(ty_size <= 128);
340334 result[0] = .integer;
341335 if (ty_size > 64) result[1] = .integer;
......@@ -344,15 +338,15 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
344338 if (ty_size > 64)
345339 return memory_class;
346340
347 const fields = ty.unionFields();
341 const fields = ty.unionFields(mod);
348342 for (fields.values()) |field| {
349343 if (field.abi_align != 0) {
350 if (field.abi_align < field.ty.abiAlignment(target)) {
344 if (field.abi_align < field.ty.abiAlignment(mod)) {
351345 return memory_class;
352346 }
353347 }
354348 // Combine this field with the previous one.
355 const field_class = classifySystemV(field.ty, target, .other);
349 const field_class = classifySystemV(field.ty, mod, .other);
356350 for (&result, 0..) |*result_item, i| {
357351 const field_item = field_class[i];
358352 // "If both classes are equal, this is the resulting class."
......@@ -426,7 +420,7 @@ pub fn classifySystemV(ty: Type, target: Target, ctx: Context) [8]Class {
426420 return result;
427421 },
428422 .Array => {
429 const ty_size = ty.abiSize(target);
423 const ty_size = ty.abiSize(mod);
430424 if (ty_size <= 64) {
431425 result[0] = .integer;
432426 return result;
......@@ -527,10 +521,17 @@ pub const RegisterClass = struct {
527521 };
528522};
529523
524const builtin = @import("builtin");
525const std = @import("std");
526const Target = std.Target;
527const assert = std.debug.assert;
530528const testing = std.testing;
529
531530const Module = @import("../../Module.zig");
531const Register = @import("bits.zig").Register;
532const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
533const Type = @import("../../type.zig").Type;
532534const Value = @import("../../value.zig").Value;
533const builtin = @import("builtin");
534535
535536fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field {
536537 return .{
......@@ -541,34 +542,3 @@ fn _field(comptime tag: Type.Tag, offset: u32) Module.Struct.Field {
541542 .is_comptime = false,
542543 };
543544}
544
545test "C_C_D" {
546 var fields = Module.Struct.Fields{};
547 // const C_C_D = extern struct { v1: i8, v2: i8, v3: f64 };
548 try fields.ensureTotalCapacity(testing.allocator, 3);
549 defer fields.deinit(testing.allocator);
550 fields.putAssumeCapacity("v1", _field(.i8, 0));
551 fields.putAssumeCapacity("v2", _field(.i8, 1));
552 fields.putAssumeCapacity("v3", _field(.f64, 4));
553
554 var C_C_D_struct = Module.Struct{
555 .fields = fields,
556 .namespace = undefined,
557 .owner_decl = undefined,
558 .zir_index = undefined,
559 .layout = .Extern,
560 .status = .fully_resolved,
561 .known_non_opv = true,
562 .is_tuple = false,
563 };
564 var C_C_D = Type.Payload.Struct{ .data = &C_C_D_struct };
565
566 try testing.expectEqual(
567 [_]Class{ .integer, .sse, .none, .none, .none, .none, .none, .none },
568 classifySystemV(Type.initPayload(&C_C_D.base), builtin.target, .ret),
569 );
570 try testing.expectEqual(
571 [_]Class{ .integer, .sse, .none, .none, .none, .none, .none, .none },
572 classifySystemV(Type.initPayload(&C_C_D.base), builtin.target, .arg),
573 );
574}
src/codegen.zig+499-792
......@@ -14,6 +14,7 @@ const Air = @import("Air.zig");
1414const Allocator = mem.Allocator;
1515const Compilation = @import("Compilation.zig");
1616const ErrorMsg = Module.ErrorMsg;
17const InternPool = @import("InternPool.zig");
1718const Liveness = @import("Liveness.zig");
1819const Module = @import("Module.zig");
1920const Target = std.Target;
......@@ -66,7 +67,7 @@ pub const DebugInfoOutput = union(enum) {
6667pub fn generateFunction(
6768 bin_file: *link.File,
6869 src_loc: Module.SrcLoc,
69 func: *Module.Fn,
70 func_index: Module.Fn.Index,
7071 air: Air,
7172 liveness: Liveness,
7273 code: *std.ArrayList(u8),
......@@ -75,17 +76,17 @@ pub fn generateFunction(
7576 switch (bin_file.options.target.cpu.arch) {
7677 .arm,
7778 .armeb,
78 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
79 => return @import("arch/arm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
7980 .aarch64,
8081 .aarch64_be,
8182 .aarch64_32,
82 => return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
83 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
84 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
85 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
83 => return @import("arch/aarch64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
84 .riscv64 => return @import("arch/riscv64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
85 .sparc64 => return @import("arch/sparc64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
86 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
8687 .wasm32,
8788 .wasm64,
88 => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func, air, liveness, code, debug_output),
89 => return @import("arch/wasm/CodeGen.zig").generate(bin_file, src_loc, func_index, air, liveness, code, debug_output),
8990 else => unreachable,
9091 }
9192}
......@@ -139,13 +140,14 @@ pub fn generateLazySymbol(
139140 return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output);
140141 }
141142
142 if (lazy_sym.ty.isAnyError()) {
143 if (lazy_sym.ty.isAnyError(mod)) {
143144 alignment.* = 4;
144 const err_names = mod.error_name_list.items;
145 const err_names = mod.global_error_set.keys();
145146 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian);
146147 var offset = code.items.len;
147148 try code.resize((1 + err_names.len + 1) * 4);
148 for (err_names) |err_name| {
149 for (err_names) |err_name_nts| {
150 const err_name = mod.intern_pool.stringToSlice(err_name_nts);
149151 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);
150152 offset += 4;
151153 try code.ensureUnusedCapacity(err_name.len + 1);
......@@ -154,9 +156,10 @@ pub fn generateLazySymbol(
154156 }
155157 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);
156158 return Result.ok;
157 } else if (lazy_sym.ty.zigTypeTag() == .Enum) {
159 } else if (lazy_sym.ty.zigTypeTag(mod) == .Enum) {
158160 alignment.* = 1;
159 for (lazy_sym.ty.enumFields().keys()) |tag_name| {
161 for (lazy_sym.ty.enumFields(mod)) |tag_name_ip| {
162 const tag_name = mod.intern_pool.stringToSlice(tag_name_ip);
160163 try code.ensureUnusedCapacity(tag_name.len + 1);
161164 code.appendSliceAssumeCapacity(tag_name);
162165 code.appendAssumeCapacity(0);
......@@ -181,749 +184,512 @@ pub fn generateSymbol(
181184 const tracy = trace(@src());
182185 defer tracy.end();
183186
187 const mod = bin_file.options.module.?;
184188 var typed_value = arg_tv;
185 if (arg_tv.val.castTag(.runtime_value)) |rt| {
186 typed_value.val = rt.data;
189 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
190 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
191 else => {},
187192 }
188193
189 const target = bin_file.options.target;
194 const target = mod.getTarget();
190195 const endian = target.cpu.arch.endian();
191196
192 const mod = bin_file.options.module.?;
193197 log.debug("generateSymbol: ty = {}, val = {}", .{
194198 typed_value.ty.fmt(mod),
195199 typed_value.val.fmtValue(typed_value.ty, mod),
196200 });
197201
198 if (typed_value.val.isUndefDeep()) {
199 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;
202 if (typed_value.val.isUndefDeep(mod)) {
203 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
200204 try code.appendNTimes(0xaa, abi_size);
201 return Result.ok;
205 return .ok;
202206 }
203207
204 switch (typed_value.ty.zigTypeTag()) {
205 .Fn => {
206 return Result{
207 .fail = try ErrorMsg.create(
208 bin_file.allocator,
209 src_loc,
210 "TODO implement generateSymbol function pointers",
211 .{},
212 ),
213 };
214 },
215 .Float => {
216 switch (typed_value.ty.floatBits(target)) {
217 16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)),
218 32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)),
219 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)),
220 80 => {
221 writeFloat(f80, typed_value.val.toFloat(f80), target, endian, try code.addManyAsArray(10));
222 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;
223 try code.appendNTimes(0, abi_size - 10);
224 },
225 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)),
208 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
209 .int_type,
210 .ptr_type,
211 .array_type,
212 .vector_type,
213 .opt_type,
214 .anyframe_type,
215 .error_union_type,
216 .simple_type,
217 .struct_type,
218 .anon_struct_type,
219 .union_type,
220 .opaque_type,
221 .enum_type,
222 .func_type,
223 .error_set_type,
224 .inferred_error_set_type,
225 => unreachable, // types, not values
226
227 .undef, .runtime_value => unreachable, // handled above
228 .simple_value => |simple_value| switch (simple_value) {
229 .undefined,
230 .void,
231 .null,
232 .empty_struct,
233 .@"unreachable",
234 .generic_poison,
235 => unreachable, // non-runtime values
236 .false, .true => try code.append(switch (simple_value) {
237 .false => 0,
238 .true => 1,
226239 else => unreachable,
227 }
228 return Result.ok;
240 }),
229241 },
230 .Array => switch (typed_value.val.tag()) {
231 .bytes => {
232 const bytes = typed_value.val.castTag(.bytes).?.data;
233 const len = @intCast(usize, typed_value.ty.arrayLenIncludingSentinel());
234 // The bytes payload already includes the sentinel, if any
235 try code.ensureUnusedCapacity(len);
236 code.appendSliceAssumeCapacity(bytes[0..len]);
237 return Result.ok;
238 },
239 .str_lit => {
240 const str_lit = typed_value.val.castTag(.str_lit).?.data;
241 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
242 try code.ensureUnusedCapacity(bytes.len + 1);
243 code.appendSliceAssumeCapacity(bytes);
244 if (typed_value.ty.sentinel()) |sent_val| {
245 const byte = @intCast(u8, sent_val.toUnsignedInt(target));
246 code.appendAssumeCapacity(byte);
247 }
248 return Result.ok;
249 },
250 .aggregate => {
251 const elem_vals = typed_value.val.castTag(.aggregate).?.data;
252 const elem_ty = typed_value.ty.elemType();
253 const len = @intCast(usize, typed_value.ty.arrayLenIncludingSentinel());
254 for (elem_vals[0..len]) |elem_val| {
255 switch (try generateSymbol(bin_file, src_loc, .{
256 .ty = elem_ty,
257 .val = elem_val,
258 }, code, debug_output, reloc_info)) {
259 .ok => {},
260 .fail => |em| return Result{ .fail = em },
261 }
262 }
263 return Result.ok;
264 },
265 .repeated => {
266 const array = typed_value.val.castTag(.repeated).?.data;
267 const elem_ty = typed_value.ty.childType();
268 const sentinel = typed_value.ty.sentinel();
269 const len = typed_value.ty.arrayLen();
270
271 var index: u64 = 0;
272 while (index < len) : (index += 1) {
273 switch (try generateSymbol(bin_file, src_loc, .{
274 .ty = elem_ty,
275 .val = array,
276 }, code, debug_output, reloc_info)) {
277 .ok => {},
278 .fail => |em| return Result{ .fail = em },
279 }
280 }
281
282 if (sentinel) |sentinel_val| {
283 switch (try generateSymbol(bin_file, src_loc, .{
284 .ty = elem_ty,
285 .val = sentinel_val,
286 }, code, debug_output, reloc_info)) {
287 .ok => {},
288 .fail => |em| return Result{ .fail = em },
289 }
290 }
291
292 return Result.ok;
293 },
294 .empty_array_sentinel => {
295 const elem_ty = typed_value.ty.childType();
296 const sentinel_val = typed_value.ty.sentinel().?;
297 switch (try generateSymbol(bin_file, src_loc, .{
298 .ty = elem_ty,
299 .val = sentinel_val,
300 }, code, debug_output, reloc_info)) {
301 .ok => {},
302 .fail => |em| return Result{ .fail = em },
303 }
304 return Result.ok;
305 },
306 else => return Result{
307 .fail = try ErrorMsg.create(
308 bin_file.allocator,
309 src_loc,
310 "TODO implement generateSymbol for array type value: {s}",
311 .{@tagName(typed_value.val.tag())},
312 ),
313 },
242 .variable,
243 .extern_func,
244 .func,
245 .enum_literal,
246 .empty_enum_value,
247 => unreachable, // non-runtime values
248 .int => {
249 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
250 var space: Value.BigIntSpace = undefined;
251 const val = typed_value.val.toBigInt(&space, mod);
252 val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);
314253 },
315 .Pointer => switch (typed_value.val.tag()) {
316 .null_value => {
317 switch (target.ptrBitWidth()) {
318 32 => {
319 mem.writeInt(u32, try code.addManyAsArray(4), 0, endian);
320 if (typed_value.ty.isSlice()) try code.appendNTimes(0xaa, 4);
321 },
322 64 => {
323 mem.writeInt(u64, try code.addManyAsArray(8), 0, endian);
324 if (typed_value.ty.isSlice()) try code.appendNTimes(0xaa, 8);
325 },
326 else => unreachable,
327 }
328 return Result.ok;
329 },
330 .zero, .one, .int_u64, .int_big_positive => {
331 switch (target.ptrBitWidth()) {
332 32 => {
333 const x = typed_value.val.toUnsignedInt(target);
334 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, x), endian);
335 },
336 64 => {
337 const x = typed_value.val.toUnsignedInt(target);
338 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
339 },
340 else => unreachable,
341 }
342 return Result.ok;
343 },
344 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
345 bin_file,
346 src_loc,
347 typed_value,
348 switch (tag) {
349 .variable => typed_value.val.castTag(.variable).?.data.owner_decl,
350 .decl_ref => typed_value.val.castTag(.decl_ref).?.data,
351 .decl_ref_mut => typed_value.val.castTag(.decl_ref_mut).?.data.decl_index,
352 else => unreachable,
353 },
354 code,
355 debug_output,
356 reloc_info,
357 ),
358 .slice => {
359 const slice = typed_value.val.castTag(.slice).?.data;
360
361 // generate ptr
362 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
363 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
364 switch (try generateSymbol(bin_file, src_loc, .{
365 .ty = slice_ptr_field_type,
366 .val = slice.ptr,
367 }, code, debug_output, reloc_info)) {
368 .ok => {},
369 .fail => |em| return Result{ .fail = em },
370 }
371
372 // generate length
373 switch (try generateSymbol(bin_file, src_loc, .{
374 .ty = Type.initTag(.usize),
375 .val = slice.len,
376 }, code, debug_output, reloc_info)) {
377 .ok => {},
378 .fail => |em| return Result{ .fail = em },
379 }
380
381 return Result.ok;
382 },
383 .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr(
384 bin_file,
385 src_loc,
386 typed_value,
387 typed_value.val,
388 code,
389 debug_output,
390 reloc_info,
391 ),
392 else => return Result{
393 .fail = try ErrorMsg.create(
394 bin_file.allocator,
395 src_loc,
396 "TODO implement generateSymbol for pointer type value: '{s}'",
397 .{@tagName(typed_value.val.tag())},
398 ),
399 },
254 .err => |err| {
255 const int = try mod.getErrorValue(err.name);
256 try code.writer().writeInt(u16, @intCast(u16, int), endian);
400257 },
401 .Int => {
402 const info = typed_value.ty.intInfo(target);
403 if (info.bits <= 8) {
404 const x: u8 = switch (info.signedness) {
405 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),
406 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt(target))),
407 };
408 try code.append(x);
409 return Result.ok;
410 }
411 if (info.bits > 64) {
412 var bigint_buffer: Value.BigIntSpace = undefined;
413 const bigint = typed_value.val.toBigInt(&bigint_buffer, target);
414 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;
415 const start = code.items.len;
416 try code.resize(start + abi_size);
417 bigint.writeTwosComplement(code.items[start..][0..abi_size], endian);
418 return Result.ok;
419 }
420 switch (info.signedness) {
421 .unsigned => {
422 if (info.bits <= 16) {
423 const x = @intCast(u16, typed_value.val.toUnsignedInt(target));
424 mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
425 } else if (info.bits <= 32) {
426 const x = @intCast(u32, typed_value.val.toUnsignedInt(target));
427 mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
428 } else {
429 const x = typed_value.val.toUnsignedInt(target);
430 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
431 }
432 },
433 .signed => {
434 if (info.bits <= 16) {
435 const x = @intCast(i16, typed_value.val.toSignedInt(target));
436 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
437 } else if (info.bits <= 32) {
438 const x = @intCast(i32, typed_value.val.toSignedInt(target));
439 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
440 } else {
441 const x = typed_value.val.toSignedInt(target);
442 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
443 }
444 },
445 }
446 return Result.ok;
447 },
448 .Enum => {
449 var int_buffer: Value.Payload.U64 = undefined;
450 const int_val = typed_value.enumToInt(&int_buffer);
451
452 const info = typed_value.ty.intInfo(target);
453 if (info.bits <= 8) {
454 const x = @intCast(u8, int_val.toUnsignedInt(target));
455 try code.append(x);
456 return Result.ok;
457 }
458 if (info.bits > 64) {
459 return Result{
460 .fail = try ErrorMsg.create(
461 bin_file.allocator,
462 src_loc,
463 "TODO implement generateSymbol for big int enums ('{}')",
464 .{typed_value.ty.fmt(mod)},
465 ),
466 };
467 }
468 switch (info.signedness) {
469 .unsigned => {
470 if (info.bits <= 16) {
471 const x = @intCast(u16, int_val.toUnsignedInt(target));
472 mem.writeInt(u16, try code.addManyAsArray(2), x, endian);
473 } else if (info.bits <= 32) {
474 const x = @intCast(u32, int_val.toUnsignedInt(target));
475 mem.writeInt(u32, try code.addManyAsArray(4), x, endian);
476 } else {
477 const x = int_val.toUnsignedInt(target);
478 mem.writeInt(u64, try code.addManyAsArray(8), x, endian);
479 }
480 },
481 .signed => {
482 if (info.bits <= 16) {
483 const x = @intCast(i16, int_val.toSignedInt(target));
484 mem.writeInt(i16, try code.addManyAsArray(2), x, endian);
485 } else if (info.bits <= 32) {
486 const x = @intCast(i32, int_val.toSignedInt(target));
487 mem.writeInt(i32, try code.addManyAsArray(4), x, endian);
488 } else {
489 const x = int_val.toSignedInt(target);
490 mem.writeInt(i64, try code.addManyAsArray(8), x, endian);
491 }
492 },
493 }
494 return Result.ok;
495 },
496 .Bool => {
497 const x: u8 = @boolToInt(typed_value.val.toBool());
498 try code.append(x);
499 return Result.ok;
500 },
501 .Struct => {
502 if (typed_value.ty.containerLayout() == .Packed) {
503 const struct_obj = typed_value.ty.castTag(.@"struct").?.data;
504 const fields = struct_obj.fields.values();
505 const field_vals = typed_value.val.castTag(.aggregate).?.data;
506 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;
507 const current_pos = code.items.len;
508 try code.resize(current_pos + abi_size);
509 var bits: u16 = 0;
510
511 for (field_vals, 0..) |field_val, index| {
512 const field_ty = fields[index].ty;
513 // pointer may point to a decl which must be marked used
514 // but can also result in a relocation. Therefore we handle those seperately.
515 if (field_ty.zigTypeTag() == .Pointer) {
516 const field_size = math.cast(usize, field_ty.abiSize(target)) orelse return error.Overflow;
517 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
518 defer tmp_list.deinit();
519 switch (try generateSymbol(bin_file, src_loc, .{
520 .ty = field_ty,
521 .val = field_val,
522 }, &tmp_list, debug_output, reloc_info)) {
523 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
524 .fail => |em| return Result{ .fail = em },
525 }
526 } else {
527 field_val.writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable;
528 }
529 bits += @intCast(u16, field_ty.bitSize(target));
530 }
258 .error_union => |error_union| {
259 const payload_ty = typed_value.ty.errorUnionPayload(mod);
260 const err_val = switch (error_union.val) {
261 .err_name => |err_name| @intCast(u16, try mod.getErrorValue(err_name)),
262 .payload => @as(u16, 0),
263 };
531264
532 return Result.ok;
265 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
266 try code.writer().writeInt(u16, err_val, endian);
267 return .ok;
533268 }
534269
535 const struct_begin = code.items.len;
536 const field_vals = typed_value.val.castTag(.aggregate).?.data;
537 for (field_vals, 0..) |field_val, index| {
538 const field_ty = typed_value.ty.structFieldType(index);
539 if (!field_ty.hasRuntimeBits()) continue;
270 const payload_align = payload_ty.abiAlignment(mod);
271 const error_align = Type.anyerror.abiAlignment(mod);
272 const abi_align = typed_value.ty.abiAlignment(mod);
540273
274 // error value first when its type is larger than the error union's payload
275 if (error_align > payload_align) {
276 try code.writer().writeInt(u16, err_val, endian);
277 }
278
279 // emit payload part of the error union
280 {
281 const begin = code.items.len;
541282 switch (try generateSymbol(bin_file, src_loc, .{
542 .ty = field_ty,
543 .val = field_val,
283 .ty = payload_ty,
284 .val = switch (error_union.val) {
285 .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }),
286 .payload => |payload| payload,
287 }.toValue(),
544288 }, code, debug_output, reloc_info)) {
545289 .ok => {},
546 .fail => |em| return Result{ .fail = em },
290 .fail => |em| return .{ .fail = em },
547291 }
548 const unpadded_field_end = code.items.len - struct_begin;
549
550 // Pad struct members if required
551 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target);
552 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow;
292 const unpadded_end = code.items.len - begin;
293 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
294 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
553295
554296 if (padding > 0) {
555297 try code.writer().writeByteNTimes(0, padding);
556298 }
557299 }
558300
559 return Result.ok;
560 },
561 .Union => {
562 const union_obj = typed_value.val.castTag(.@"union").?.data;
563 const layout = typed_value.ty.unionGetLayout(target);
564
565 if (layout.payload_size == 0) {
566 return generateSymbol(bin_file, src_loc, .{
567 .ty = typed_value.ty.unionTagType().?,
568 .val = union_obj.tag,
569 }, code, debug_output, reloc_info);
570 }
571
572 // Check if we should store the tag first.
573 if (layout.tag_align >= layout.payload_align) {
574 switch (try generateSymbol(bin_file, src_loc, .{
575 .ty = typed_value.ty.unionTagType().?,
576 .val = union_obj.tag,
577 }, code, debug_output, reloc_info)) {
578 .ok => {},
579 .fail => |em| return Result{ .fail = em },
580 }
581 }
582
583 const union_ty = typed_value.ty.cast(Type.Payload.Union).?.data;
584 const field_index = typed_value.ty.unionTagFieldIndex(union_obj.tag, mod).?;
585 assert(union_ty.haveFieldTypes());
586 const field_ty = union_ty.fields.values()[field_index].ty;
587 if (!field_ty.hasRuntimeBits()) {
588 try code.writer().writeByteNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
589 } else {
590 switch (try generateSymbol(bin_file, src_loc, .{
591 .ty = field_ty,
592 .val = union_obj.val,
593 }, code, debug_output, reloc_info)) {
594 .ok => {},
595 .fail => |em| return Result{ .fail = em },
596 }
301 // Payload size is larger than error set, so emit our error set last
302 if (error_align <= payload_align) {
303 const begin = code.items.len;
304 try code.writer().writeInt(u16, err_val, endian);
305 const unpadded_end = code.items.len - begin;
306 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
307 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
597308
598 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(target)) orelse return error.Overflow;
599309 if (padding > 0) {
600310 try code.writer().writeByteNTimes(0, padding);
601311 }
602312 }
603
604 if (layout.tag_size > 0) {
313 },
314 .enum_tag => |enum_tag| {
315 const int_tag_ty = typed_value.ty.intTagType(mod);
316 switch (try generateSymbol(bin_file, src_loc, .{
317 .ty = int_tag_ty,
318 .val = try mod.getCoerced(enum_tag.int.toValue(), int_tag_ty),
319 }, code, debug_output, reloc_info)) {
320 .ok => {},
321 .fail => |em| return .{ .fail = em },
322 }
323 },
324 .float => |float| switch (float.storage) {
325 .f16 => |f16_val| writeFloat(f16, f16_val, target, endian, try code.addManyAsArray(2)),
326 .f32 => |f32_val| writeFloat(f32, f32_val, target, endian, try code.addManyAsArray(4)),
327 .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(8)),
328 .f80 => |f80_val| {
329 writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(10));
330 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
331 try code.appendNTimes(0, abi_size - 10);
332 },
333 .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)),
334 },
335 .ptr => |ptr| {
336 // generate ptr
337 switch (try lowerParentPtr(bin_file, src_loc, switch (ptr.len) {
338 .none => typed_value.val,
339 else => typed_value.val.slicePtr(mod),
340 }.toIntern(), code, debug_output, reloc_info)) {
341 .ok => {},
342 .fail => |em| return .{ .fail = em },
343 }
344 if (ptr.len != .none) {
345 // generate len
605346 switch (try generateSymbol(bin_file, src_loc, .{
606 .ty = union_ty.tag_ty,
607 .val = union_obj.tag,
347 .ty = Type.usize,
348 .val = ptr.len.toValue(),
608349 }, code, debug_output, reloc_info)) {
609350 .ok => {},
610351 .fail => |em| return Result{ .fail = em },
611352 }
612353 }
613
614 if (layout.padding > 0) {
615 try code.writer().writeByteNTimes(0, layout.padding);
616 }
617
618 return Result.ok;
619354 },
620 .Optional => {
621 var opt_buf: Type.Payload.ElemType = undefined;
622 const payload_type = typed_value.ty.optionalChild(&opt_buf);
623 const is_pl = !typed_value.val.isNull();
624 const abi_size = math.cast(usize, typed_value.ty.abiSize(target)) orelse return error.Overflow;
625
626 if (!payload_type.hasRuntimeBits()) {
627 try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size);
628 return Result.ok;
629 }
355 .opt => {
356 const payload_type = typed_value.ty.optionalChild(mod);
357 const payload_val = typed_value.val.optionalValue(mod);
358 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow;
630359
631 if (typed_value.ty.optionalReprIsPayload()) {
632 if (typed_value.val.castTag(.opt_payload)) |payload| {
360 if (typed_value.ty.optionalReprIsPayload(mod)) {
361 if (payload_val) |value| {
633362 switch (try generateSymbol(bin_file, src_loc, .{
634363 .ty = payload_type,
635 .val = payload.data,
364 .val = value,
636365 }, code, debug_output, reloc_info)) {
637366 .ok => {},
638367 .fail => |em| return Result{ .fail = em },
639368 }
640 } else if (!typed_value.val.isNull()) {
369 } else {
370 try code.writer().writeByteNTimes(0, abi_size);
371 }
372 } else {
373 const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1;
374 if (payload_type.hasRuntimeBits(mod)) {
375 const value = payload_val orelse (try mod.intern(.{ .undef = payload_type.toIntern() })).toValue();
641376 switch (try generateSymbol(bin_file, src_loc, .{
642377 .ty = payload_type,
643 .val = typed_value.val,
378 .val = value,
644379 }, code, debug_output, reloc_info)) {
645380 .ok => {},
646381 .fail => |em| return Result{ .fail = em },
647382 }
648 } else {
649 try code.writer().writeByteNTimes(0, abi_size);
650383 }
651
652 return Result.ok;
384 try code.writer().writeByte(@boolToInt(payload_val != null));
385 try code.writer().writeByteNTimes(0, padding);
653386 }
387 },
388 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(typed_value.ty.toIntern())) {
389 .array_type => |array_type| switch (aggregate.storage) {
390 .bytes => |bytes| try code.appendSlice(bytes),
391 .elems, .repeated_elem => {
392 var index: u64 = 0;
393 var len_including_sentinel =
394 array_type.len + @boolToInt(array_type.sentinel != .none);
395 while (index < len_including_sentinel) : (index += 1) {
396 switch (try generateSymbol(bin_file, src_loc, .{
397 .ty = array_type.child.toType(),
398 .val = switch (aggregate.storage) {
399 .bytes => unreachable,
400 .elems => |elems| elems[@intCast(usize, index)],
401 .repeated_elem => |elem| elem,
402 }.toValue(),
403 }, code, debug_output, reloc_info)) {
404 .ok => {},
405 .fail => |em| return .{ .fail = em },
406 }
407 }
408 },
409 },
410 .vector_type => |vector_type| {
411 switch (aggregate.storage) {
412 .bytes => |bytes| try code.appendSlice(bytes),
413 .elems, .repeated_elem => {
414 var index: u64 = 0;
415 while (index < vector_type.len) : (index += 1) {
416 switch (try generateSymbol(bin_file, src_loc, .{
417 .ty = vector_type.child.toType(),
418 .val = switch (aggregate.storage) {
419 .bytes => unreachable,
420 .elems => |elems| elems[@intCast(usize, index)],
421 .repeated_elem => |elem| elem,
422 }.toValue(),
423 }, code, debug_output, reloc_info)) {
424 .ok => {},
425 .fail => |em| return .{ .fail = em },
426 }
427 }
428 },
429 }
654430
655 const padding = abi_size - (math.cast(usize, payload_type.abiSize(target)) orelse return error.Overflow) - 1;
656 const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef);
657 switch (try generateSymbol(bin_file, src_loc, .{
658 .ty = payload_type,
659 .val = value,
660 }, code, debug_output, reloc_info)) {
661 .ok => {},
662 .fail => |em| return Result{ .fail = em },
663 }
664 try code.writer().writeByte(@boolToInt(is_pl));
665 try code.writer().writeByteNTimes(0, padding);
431 const padding = math.cast(usize, typed_value.ty.abiSize(mod) -
432 (math.divCeil(u64, vector_type.child.toType().bitSize(mod) * vector_type.len, 8) catch |err| switch (err) {
433 error.DivisionByZero => unreachable,
434 else => |e| return e,
435 })) orelse return error.Overflow;
436 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
437 },
438 .anon_struct_type => |tuple| {
439 const struct_begin = code.items.len;
440 for (tuple.types, tuple.values, 0..) |field_ty, comptime_val, index| {
441 if (comptime_val != .none) continue;
442 if (!field_ty.toType().hasRuntimeBits(mod)) continue;
443
444 const field_val = switch (aggregate.storage) {
445 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
446 .ty = field_ty,
447 .storage = .{ .u64 = bytes[index] },
448 } }),
449 .elems => |elems| elems[index],
450 .repeated_elem => |elem| elem,
451 };
452
453 switch (try generateSymbol(bin_file, src_loc, .{
454 .ty = field_ty.toType(),
455 .val = field_val.toValue(),
456 }, code, debug_output, reloc_info)) {
457 .ok => {},
458 .fail => |em| return Result{ .fail = em },
459 }
460 const unpadded_field_end = code.items.len - struct_begin;
461
462 // Pad struct members if required
463 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod);
464 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse
465 return error.Overflow;
666466
667 return Result.ok;
467 if (padding > 0) {
468 try code.writer().writeByteNTimes(0, padding);
469 }
470 }
471 },
472 .struct_type => |struct_type| {
473 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
474
475 if (struct_obj.layout == .Packed) {
476 const fields = struct_obj.fields.values();
477 const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse
478 return error.Overflow;
479 const current_pos = code.items.len;
480 try code.resize(current_pos + abi_size);
481 var bits: u16 = 0;
482
483 for (fields, 0..) |field, index| {
484 const field_ty = field.ty;
485
486 const field_val = switch (aggregate.storage) {
487 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
488 .ty = field_ty.toIntern(),
489 .storage = .{ .u64 = bytes[index] },
490 } }),
491 .elems => |elems| elems[index],
492 .repeated_elem => |elem| elem,
493 };
494
495 // pointer may point to a decl which must be marked used
496 // but can also result in a relocation. Therefore we handle those separately.
497 if (field_ty.zigTypeTag(mod) == .Pointer) {
498 const field_size = math.cast(usize, field_ty.abiSize(mod)) orelse
499 return error.Overflow;
500 var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size);
501 defer tmp_list.deinit();
502 switch (try generateSymbol(bin_file, src_loc, .{
503 .ty = field_ty,
504 .val = field_val.toValue(),
505 }, &tmp_list, debug_output, reloc_info)) {
506 .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items),
507 .fail => |em| return Result{ .fail = em },
508 }
509 } else {
510 field_val.toValue().writeToPackedMemory(field_ty, mod, code.items[current_pos..], bits) catch unreachable;
511 }
512 bits += @intCast(u16, field_ty.bitSize(mod));
513 }
514 } else {
515 const struct_begin = code.items.len;
516 for (struct_obj.fields.values(), 0..) |field, index| {
517 const field_ty = field.ty;
518 if (!field_ty.hasRuntimeBits(mod)) continue;
519
520 const field_val = switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).aggregate.storage) {
521 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
522 .ty = field_ty.toIntern(),
523 .storage = .{ .u64 = bytes[index] },
524 } }),
525 .elems => |elems| elems[index],
526 .repeated_elem => |elem| elem,
527 };
528
529 switch (try generateSymbol(bin_file, src_loc, .{
530 .ty = field_ty,
531 .val = field_val.toValue(),
532 }, code, debug_output, reloc_info)) {
533 .ok => {},
534 .fail => |em| return Result{ .fail = em },
535 }
536 const unpadded_field_end = code.items.len - struct_begin;
537
538 // Pad struct members if required
539 const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod);
540 const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow;
541
542 if (padding > 0) {
543 try code.writer().writeByteNTimes(0, padding);
544 }
545 }
546 }
547 },
548 else => unreachable,
668549 },
669 .ErrorUnion => {
670 const error_ty = typed_value.ty.errorUnionSet();
671 const payload_ty = typed_value.ty.errorUnionPayload();
672 const is_payload = typed_value.val.errorUnionIsPayload();
550 .un => |un| {
551 const layout = typed_value.ty.unionGetLayout(mod);
673552
674 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
675 const err_val = if (is_payload) Value.initTag(.zero) else typed_value.val;
553 if (layout.payload_size == 0) {
676554 return generateSymbol(bin_file, src_loc, .{
677 .ty = error_ty,
678 .val = err_val,
555 .ty = typed_value.ty.unionTagType(mod).?,
556 .val = un.tag.toValue(),
679557 }, code, debug_output, reloc_info);
680558 }
681559
682 const payload_align = payload_ty.abiAlignment(target);
683 const error_align = Type.anyerror.abiAlignment(target);
684 const abi_align = typed_value.ty.abiAlignment(target);
685
686 // error value first when its type is larger than the error union's payload
687 if (error_align > payload_align) {
560 // Check if we should store the tag first.
561 if (layout.tag_align >= layout.payload_align) {
688562 switch (try generateSymbol(bin_file, src_loc, .{
689 .ty = error_ty,
690 .val = if (is_payload) Value.initTag(.zero) else typed_value.val,
563 .ty = typed_value.ty.unionTagType(mod).?,
564 .val = un.tag.toValue(),
691565 }, code, debug_output, reloc_info)) {
692566 .ok => {},
693567 .fail => |em| return Result{ .fail = em },
694568 }
695569 }
696570
697 // emit payload part of the error union
698 {
699 const begin = code.items.len;
700 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
571 const union_ty = mod.typeToUnion(typed_value.ty).?;
572 const field_index = typed_value.ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
573 assert(union_ty.haveFieldTypes());
574 const field_ty = union_ty.fields.values()[field_index].ty;
575 if (!field_ty.hasRuntimeBits(mod)) {
576 try code.writer().writeByteNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow);
577 } else {
701578 switch (try generateSymbol(bin_file, src_loc, .{
702 .ty = payload_ty,
703 .val = payload_val,
579 .ty = field_ty,
580 .val = un.val.toValue(),
704581 }, code, debug_output, reloc_info)) {
705582 .ok => {},
706583 .fail => |em| return Result{ .fail = em },
707584 }
708 const unpadded_end = code.items.len - begin;
709 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
710 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
711585
586 const padding = math.cast(usize, layout.payload_size - field_ty.abiSize(mod)) orelse return error.Overflow;
712587 if (padding > 0) {
713588 try code.writer().writeByteNTimes(0, padding);
714589 }
715590 }
716591
717 // Payload size is larger than error set, so emit our error set last
718 if (error_align <= payload_align) {
719 const begin = code.items.len;
592 if (layout.tag_size > 0) {
720593 switch (try generateSymbol(bin_file, src_loc, .{
721 .ty = error_ty,
722 .val = if (is_payload) Value.initTag(.zero) else typed_value.val,
594 .ty = union_ty.tag_ty,
595 .val = un.tag.toValue(),
723596 }, code, debug_output, reloc_info)) {
724597 .ok => {},
725598 .fail => |em| return Result{ .fail = em },
726599 }
727 const unpadded_end = code.items.len - begin;
728 const padded_end = mem.alignForwardGeneric(u64, unpadded_end, abi_align);
729 const padding = math.cast(usize, padded_end - unpadded_end) orelse return error.Overflow;
730
731 if (padding > 0) {
732 try code.writer().writeByteNTimes(0, padding);
733 }
734 }
735
736 return Result.ok;
737 },
738 .ErrorSet => {
739 switch (typed_value.val.tag()) {
740 .@"error" => {
741 const name = typed_value.val.getError().?;
742 const kv = try bin_file.options.module.?.getErrorValue(name);
743 try code.writer().writeInt(u32, kv.value, endian);
744 },
745 else => {
746 try code.writer().writeByteNTimes(0, @intCast(usize, Type.anyerror.abiSize(target)));
747 },
748600 }
749 return Result.ok;
750601 },
751 .Vector => switch (typed_value.val.tag()) {
752 .bytes => {
753 const bytes = typed_value.val.castTag(.bytes).?.data;
754 const len = math.cast(usize, typed_value.ty.arrayLen()) orelse return error.Overflow;
755 const padding = math.cast(usize, typed_value.ty.abiSize(target) - len) orelse
756 return error.Overflow;
757 try code.ensureUnusedCapacity(len + padding);
758 code.appendSliceAssumeCapacity(bytes[0..len]);
759 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
760 return Result.ok;
761 },
762 .aggregate => {
763 const elem_vals = typed_value.val.castTag(.aggregate).?.data;
764 const elem_ty = typed_value.ty.elemType();
765 const len = math.cast(usize, typed_value.ty.arrayLen()) orelse return error.Overflow;
766 const padding = math.cast(usize, typed_value.ty.abiSize(target) -
767 (math.divCeil(u64, elem_ty.bitSize(target) * len, 8) catch |err| switch (err) {
768 error.DivisionByZero => unreachable,
769 else => |e| return e,
770 })) orelse return error.Overflow;
771 for (elem_vals[0..len]) |elem_val| {
772 switch (try generateSymbol(bin_file, src_loc, .{
773 .ty = elem_ty,
774 .val = elem_val,
775 }, code, debug_output, reloc_info)) {
776 .ok => {},
777 .fail => |em| return Result{ .fail = em },
778 }
779 }
780 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
781 return Result.ok;
782 },
783 .repeated => {
784 const array = typed_value.val.castTag(.repeated).?.data;
785 const elem_ty = typed_value.ty.childType();
786 const len = typed_value.ty.arrayLen();
787 const padding = math.cast(usize, typed_value.ty.abiSize(target) -
788 (math.divCeil(u64, elem_ty.bitSize(target) * len, 8) catch |err| switch (err) {
789 error.DivisionByZero => unreachable,
790 else => |e| return e,
791 })) orelse return error.Overflow;
792 var index: u64 = 0;
793 while (index < len) : (index += 1) {
794 switch (try generateSymbol(bin_file, src_loc, .{
795 .ty = elem_ty,
796 .val = array,
797 }, code, debug_output, reloc_info)) {
798 .ok => {},
799 .fail => |em| return Result{ .fail = em },
800 }
801 }
802 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
803 return Result.ok;
804 },
805 .str_lit => {
806 const str_lit = typed_value.val.castTag(.str_lit).?.data;
807 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
808 const padding = math.cast(usize, typed_value.ty.abiSize(target) - str_lit.len) orelse
809 return error.Overflow;
810 try code.ensureUnusedCapacity(str_lit.len + padding);
811 code.appendSliceAssumeCapacity(bytes);
812 if (padding > 0) try code.writer().writeByteNTimes(0, padding);
813 return Result.ok;
814 },
815 else => unreachable,
816 },
817 else => |tag| return Result{ .fail = try ErrorMsg.create(
818 bin_file.allocator,
819 src_loc,
820 "TODO implement generateSymbol for type '{s}'",
821 .{@tagName(tag)},
822 ) },
602 .memoized_call => unreachable,
823603 }
604 return .ok;
824605}
825606
826607fn lowerParentPtr(
827608 bin_file: *link.File,
828609 src_loc: Module.SrcLoc,
829 typed_value: TypedValue,
830 parent_ptr: Value,
610 parent_ptr: InternPool.Index,
831611 code: *std.ArrayList(u8),
832612 debug_output: DebugInfoOutput,
833613 reloc_info: RelocInfo,
834614) CodeGenError!Result {
835 const target = bin_file.options.target;
836 switch (parent_ptr.tag()) {
837 .field_ptr => {
838 const field_ptr = parent_ptr.castTag(.field_ptr).?.data;
615 const mod = bin_file.options.module.?;
616 const ptr = mod.intern_pool.indexToKey(parent_ptr).ptr;
617 assert(ptr.len == .none);
618 return switch (ptr.addr) {
619 .decl, .mut_decl => try lowerDeclRef(
620 bin_file,
621 src_loc,
622 switch (ptr.addr) {
623 .decl => |decl| decl,
624 .mut_decl => |mut_decl| mut_decl.decl,
625 else => unreachable,
626 },
627 code,
628 debug_output,
629 reloc_info,
630 ),
631 .int => |int| try generateSymbol(bin_file, src_loc, .{
632 .ty = Type.usize,
633 .val = int.toValue(),
634 }, code, debug_output, reloc_info),
635 .eu_payload => |eu_payload| try lowerParentPtr(
636 bin_file,
637 src_loc,
638 eu_payload,
639 code,
640 debug_output,
641 reloc_info.offset(@intCast(u32, errUnionPayloadOffset(
642 mod.intern_pool.typeOf(eu_payload).toType(),
643 mod,
644 ))),
645 ),
646 .opt_payload => |opt_payload| try lowerParentPtr(
647 bin_file,
648 src_loc,
649 opt_payload,
650 code,
651 debug_output,
652 reloc_info,
653 ),
654 .elem => |elem| try lowerParentPtr(
655 bin_file,
656 src_loc,
657 elem.base,
658 code,
659 debug_output,
660 reloc_info.offset(@intCast(u32, elem.index *
661 mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).abiSize(mod))),
662 ),
663 .field => |field| {
664 const base_type = mod.intern_pool.indexToKey(mod.intern_pool.typeOf(field.base)).ptr_type.child;
839665 return lowerParentPtr(
840666 bin_file,
841667 src_loc,
842 typed_value,
843 field_ptr.container_ptr,
668 field.base,
844669 code,
845670 debug_output,
846 reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag()) {
847 .Pointer => offset: {
848 assert(field_ptr.container_ty.isSlice());
849 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
850 break :offset switch (field_ptr.field_index) {
671 reloc_info.offset(switch (mod.intern_pool.indexToKey(base_type)) {
672 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
673 .One, .Many, .C => unreachable,
674 .Slice => switch (field.index) {
851675 0 => 0,
852 1 => field_ptr.container_ty.slicePtrFieldType(&buf).abiSize(target),
676 1 => @divExact(mod.getTarget().ptrBitWidth(), 8),
853677 else => unreachable,
854 };
678 },
855679 },
856 .Struct, .Union => field_ptr.container_ty.structFieldOffset(
857 field_ptr.field_index,
858 target,
859 ),
860 else => return Result{ .fail = try ErrorMsg.create(
861 bin_file.allocator,
862 src_loc,
863 "TODO implement lowerParentPtr for field_ptr with a container of type {}",
864 .{field_ptr.container_ty.fmt(bin_file.options.module.?)},
865 ) },
866 })),
867 );
868 },
869 .elem_ptr => {
870 const elem_ptr = parent_ptr.castTag(.elem_ptr).?.data;
871 return lowerParentPtr(
872 bin_file,
873 src_loc,
874 typed_value,
875 elem_ptr.array_ptr,
876 code,
877 debug_output,
878 reloc_info.offset(@intCast(u32, elem_ptr.index * elem_ptr.elem_ty.abiSize(target))),
879 );
880 },
881 .opt_payload_ptr => {
882 const opt_payload_ptr = parent_ptr.castTag(.opt_payload_ptr).?.data;
883 return lowerParentPtr(
884 bin_file,
885 src_loc,
886 typed_value,
887 opt_payload_ptr.container_ptr,
888 code,
889 debug_output,
890 reloc_info,
891 );
892 },
893 .eu_payload_ptr => {
894 const eu_payload_ptr = parent_ptr.castTag(.eu_payload_ptr).?.data;
895 const pl_ty = eu_payload_ptr.container_ty.errorUnionPayload();
896 return lowerParentPtr(
897 bin_file,
898 src_loc,
899 typed_value,
900 eu_payload_ptr.container_ptr,
901 code,
902 debug_output,
903 reloc_info.offset(@intCast(u32, errUnionPayloadOffset(pl_ty, target))),
680 .struct_type,
681 .anon_struct_type,
682 .union_type,
683 => @intCast(u32, base_type.toType().structFieldOffset(
684 @intCast(u32, field.index),
685 mod,
686 )),
687 else => unreachable,
688 }),
904689 );
905690 },
906 .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
907 bin_file,
908 src_loc,
909 typed_value,
910 switch (tag) {
911 .variable => parent_ptr.castTag(.variable).?.data.owner_decl,
912 .decl_ref => parent_ptr.castTag(.decl_ref).?.data,
913 .decl_ref_mut => parent_ptr.castTag(.decl_ref_mut).?.data.decl_index,
914 else => unreachable,
915 },
916 code,
917 debug_output,
918 reloc_info,
919 ),
920 else => |tag| return Result{ .fail = try ErrorMsg.create(
921 bin_file.allocator,
922 src_loc,
923 "TODO implement lowerParentPtr for type '{s}'",
924 .{@tagName(tag)},
925 ) },
926 }
691 .comptime_field => unreachable,
692 };
927693}
928694
929695const RelocInfo = struct {
......@@ -938,51 +704,25 @@ const RelocInfo = struct {
938704fn lowerDeclRef(
939705 bin_file: *link.File,
940706 src_loc: Module.SrcLoc,
941 typed_value: TypedValue,
942707 decl_index: Module.Decl.Index,
943708 code: *std.ArrayList(u8),
944709 debug_output: DebugInfoOutput,
945710 reloc_info: RelocInfo,
946711) CodeGenError!Result {
712 _ = src_loc;
713 _ = debug_output;
947714 const target = bin_file.options.target;
948 const module = bin_file.options.module.?;
949 if (typed_value.ty.isSlice()) {
950 // generate ptr
951 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
952 const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf);
953 switch (try generateSymbol(bin_file, src_loc, .{
954 .ty = slice_ptr_field_type,
955 .val = typed_value.val,
956 }, code, debug_output, reloc_info)) {
957 .ok => {},
958 .fail => |em| return Result{ .fail = em },
959 }
960
961 // generate length
962 var slice_len: Value.Payload.U64 = .{
963 .base = .{ .tag = .int_u64 },
964 .data = typed_value.val.sliceLen(module),
965 };
966 switch (try generateSymbol(bin_file, src_loc, .{
967 .ty = Type.usize,
968 .val = Value.initPayload(&slice_len.base),
969 }, code, debug_output, reloc_info)) {
970 .ok => {},
971 .fail => |em| return Result{ .fail = em },
972 }
973
974 return Result.ok;
975 }
715 const mod = bin_file.options.module.?;
976716
977717 const ptr_width = target.ptrBitWidth();
978 const decl = module.declPtr(decl_index);
979 const is_fn_body = decl.ty.zigTypeTag() == .Fn;
980 if (!is_fn_body and !decl.ty.hasRuntimeBits()) {
718 const decl = mod.declPtr(decl_index);
719 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
720 if (!is_fn_body and !decl.ty.hasRuntimeBits(mod)) {
981721 try code.writer().writeByteNTimes(0xaa, @divExact(ptr_width, 8));
982722 return Result.ok;
983723 }
984724
985 module.markDeclAlive(decl);
725 try mod.markDeclAlive(decl);
986726
987727 const vaddr = try bin_file.getDeclVAddr(decl_index, .{
988728 .parent_atom_index = reloc_info.parent_atom_index,
......@@ -1059,16 +799,16 @@ fn genDeclRef(
1059799 tv: TypedValue,
1060800 decl_index: Module.Decl.Index,
1061801) CodeGenError!GenResult {
1062 const module = bin_file.options.module.?;
1063 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(module), tv.val.fmtValue(tv.ty, module) });
802 const mod = bin_file.options.module.?;
803 log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(mod), tv.val.fmtValue(tv.ty, mod) });
1064804
1065805 const target = bin_file.options.target;
1066806 const ptr_bits = target.ptrBitWidth();
1067807 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1068808
1069 const decl = module.declPtr(decl_index);
809 const decl = mod.declPtr(decl_index);
1070810
1071 if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
811 if (!decl.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
1072812 const imm: u64 = switch (ptr_bytes) {
1073813 1 => 0xaa,
1074814 2 => 0xaaaa,
......@@ -1080,20 +820,20 @@ fn genDeclRef(
1080820 }
1081821
1082822 // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`?
1083 if (tv.ty.castPtrToFn()) |fn_ty| {
1084 if (fn_ty.fnInfo().is_generic) {
1085 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(target) });
823 if (tv.ty.castPtrToFn(mod)) |fn_ty| {
824 if (mod.typeToFunc(fn_ty).?.is_generic) {
825 return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(mod) });
1086826 }
1087 } else if (tv.ty.zigTypeTag() == .Pointer) {
1088 const elem_ty = tv.ty.elemType2();
1089 if (!elem_ty.hasRuntimeBits()) {
1090 return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(target) });
827 } else if (tv.ty.zigTypeTag(mod) == .Pointer) {
828 const elem_ty = tv.ty.elemType2(mod);
829 if (!elem_ty.hasRuntimeBits(mod)) {
830 return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(mod) });
1091831 }
1092832 }
1093833
1094 module.markDeclAlive(decl);
834 try mod.markDeclAlive(decl);
1095835
1096 const is_threadlocal = tv.val.isPtrToThreadLocal(module) and !bin_file.options.single_threaded;
836 const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !bin_file.options.single_threaded;
1097837
1098838 if (bin_file.cast(link.File.Elf)) |elf_file| {
1099839 const atom_index = try elf_file.getOrCreateAtomForDecl(decl_index);
......@@ -1157,57 +897,56 @@ pub fn genTypedValue(
1157897 arg_tv: TypedValue,
1158898 owner_decl_index: Module.Decl.Index,
1159899) CodeGenError!GenResult {
900 const mod = bin_file.options.module.?;
1160901 var typed_value = arg_tv;
1161 if (typed_value.val.castTag(.runtime_value)) |rt| {
1162 typed_value.val = rt.data;
902 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
903 .runtime_value => |rt| typed_value.val = rt.val.toValue(),
904 else => {},
1163905 }
1164906
1165 const mod = bin_file.options.module.?;
1166907 log.debug("genTypedValue: ty = {}, val = {}", .{
1167908 typed_value.ty.fmt(mod),
1168909 typed_value.val.fmtValue(typed_value.ty, mod),
1169910 });
1170911
1171 if (typed_value.val.isUndef())
912 if (typed_value.val.isUndef(mod))
1172913 return GenResult.mcv(.undef);
1173914
1174915 const target = bin_file.options.target;
1175916 const ptr_bits = target.ptrBitWidth();
1176917
1177 if (!typed_value.ty.isSlice()) {
1178 if (typed_value.val.castTag(.variable)) |payload| {
1179 return genDeclRef(bin_file, src_loc, typed_value, payload.data.owner_decl);
1180 }
1181 if (typed_value.val.castTag(.decl_ref)) |payload| {
1182 return genDeclRef(bin_file, src_loc, typed_value, payload.data);
1183 }
1184 if (typed_value.val.castTag(.decl_ref_mut)) |payload| {
1185 return genDeclRef(bin_file, src_loc, typed_value, payload.data.decl_index);
1186 }
1187 }
918 if (!typed_value.ty.isSlice(mod)) switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
919 .ptr => |ptr| switch (ptr.addr) {
920 .decl => |decl| return genDeclRef(bin_file, src_loc, typed_value, decl),
921 .mut_decl => |mut_decl| return genDeclRef(bin_file, src_loc, typed_value, mut_decl.decl),
922 else => {},
923 },
924 else => {},
925 };
1188926
1189 switch (typed_value.ty.zigTypeTag()) {
927 switch (typed_value.ty.zigTypeTag(mod)) {
1190928 .Void => return GenResult.mcv(.none),
1191 .Pointer => switch (typed_value.ty.ptrSize()) {
929 .Pointer => switch (typed_value.ty.ptrSize(mod)) {
1192930 .Slice => {},
1193 else => {
1194 switch (typed_value.val.tag()) {
1195 .null_value => {
1196 return GenResult.mcv(.{ .immediate = 0 });
1197 },
1198 .int_u64 => {
1199 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(target) });
931 else => switch (typed_value.val.toIntern()) {
932 .null_value => {
933 return GenResult.mcv(.{ .immediate = 0 });
934 },
935 .none => {},
936 else => switch (mod.intern_pool.indexToKey(typed_value.val.toIntern())) {
937 .int => {
938 return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(mod) });
1200939 },
1201940 else => {},
1202 }
941 },
1203942 },
1204943 },
1205944 .Int => {
1206 const info = typed_value.ty.intInfo(target);
945 const info = typed_value.ty.intInfo(mod);
1207946 if (info.bits <= ptr_bits) {
1208947 const unsigned = switch (info.signedness) {
1209 .signed => @bitCast(u64, typed_value.val.toSignedInt(target)),
1210 .unsigned => typed_value.val.toUnsignedInt(target),
948 .signed => @bitCast(u64, typed_value.val.toSignedInt(mod)),
949 .unsigned => typed_value.val.toUnsignedInt(mod),
1211950 };
1212951 return GenResult.mcv(.{ .immediate = unsigned });
1213952 }
......@@ -1216,78 +955,46 @@ pub fn genTypedValue(
1216955 return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) });
1217956 },
1218957 .Optional => {
1219 if (typed_value.ty.isPtrLikeOptional()) {
1220 if (typed_value.val.tag() == .null_value) return GenResult.mcv(.{ .immediate = 0 });
1221
1222 var buf: Type.Payload.ElemType = undefined;
958 if (typed_value.ty.isPtrLikeOptional(mod)) {
1223959 return genTypedValue(bin_file, src_loc, .{
1224 .ty = typed_value.ty.optionalChild(&buf),
1225 .val = if (typed_value.val.castTag(.opt_payload)) |pl| pl.data else typed_value.val,
960 .ty = typed_value.ty.optionalChild(mod),
961 .val = typed_value.val.optionalValue(mod) orelse return GenResult.mcv(.{ .immediate = 0 }),
1226962 }, owner_decl_index);
1227 } else if (typed_value.ty.abiSize(target) == 1) {
1228 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull()) });
963 } else if (typed_value.ty.abiSize(mod) == 1) {
964 return GenResult.mcv(.{ .immediate = @boolToInt(!typed_value.val.isNull(mod)) });
1229965 }
1230966 },
1231967 .Enum => {
1232 if (typed_value.val.castTag(.enum_field_index)) |field_index| {
1233 switch (typed_value.ty.tag()) {
1234 .enum_simple => {
1235 return GenResult.mcv(.{ .immediate = field_index.data });
1236 },
1237 .enum_numbered, .enum_full, .enum_nonexhaustive => {
1238 const enum_values = if (typed_value.ty.castTag(.enum_numbered)) |pl|
1239 pl.data.values
1240 else
1241 typed_value.ty.cast(Type.Payload.EnumFull).?.data.values;
1242 if (enum_values.count() != 0) {
1243 const tag_val = enum_values.keys()[field_index.data];
1244 var buf: Type.Payload.Bits = undefined;
1245 return genTypedValue(bin_file, src_loc, .{
1246 .ty = typed_value.ty.intTagType(&buf),
1247 .val = tag_val,
1248 }, owner_decl_index);
1249 } else {
1250 return GenResult.mcv(.{ .immediate = field_index.data });
1251 }
1252 },
1253 else => unreachable,
1254 }
1255 } else {
1256 var int_tag_buffer: Type.Payload.Bits = undefined;
1257 const int_tag_ty = typed_value.ty.intTagType(&int_tag_buffer);
1258 return genTypedValue(bin_file, src_loc, .{
1259 .ty = int_tag_ty,
1260 .val = typed_value.val,
1261 }, owner_decl_index);
1262 }
968 const enum_tag = mod.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag;
969 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
970 return genTypedValue(bin_file, src_loc, .{
971 .ty = int_tag_ty.toType(),
972 .val = enum_tag.int.toValue(),
973 }, owner_decl_index);
1263974 },
1264975 .ErrorSet => {
1265 switch (typed_value.val.tag()) {
1266 .@"error" => {
1267 const err_name = typed_value.val.castTag(.@"error").?.data.name;
1268 const module = bin_file.options.module.?;
1269 const global_error_set = module.global_error_set;
1270 const error_index = global_error_set.get(err_name).?;
1271 return GenResult.mcv(.{ .immediate = error_index });
1272 },
1273 else => {
1274 // In this case we are rendering an error union which has a 0 bits payload.
1275 return GenResult.mcv(.{ .immediate = 0 });
1276 },
1277 }
976 const err_name = mod.intern_pool.indexToKey(typed_value.val.toIntern()).err.name;
977 const error_index = mod.global_error_set.getIndex(err_name).?;
978 return GenResult.mcv(.{ .immediate = error_index });
1278979 },
1279980 .ErrorUnion => {
1280 const error_type = typed_value.ty.errorUnionSet();
1281 const payload_type = typed_value.ty.errorUnionPayload();
1282 const is_pl = typed_value.val.errorUnionIsPayload();
1283
1284 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
981 const err_type = typed_value.ty.errorUnionSet(mod);
982 const payload_type = typed_value.ty.errorUnionPayload(mod);
983 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
1285984 // We use the error type directly as the type.
1286 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
1287 return genTypedValue(bin_file, src_loc, .{
1288 .ty = error_type,
1289 .val = err_val,
1290 }, owner_decl_index);
985 switch (mod.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) {
986 .err_name => |err_name| return genTypedValue(bin_file, src_loc, .{
987 .ty = err_type,
988 .val = (try mod.intern(.{ .err = .{
989 .ty = err_type.toIntern(),
990 .name = err_name,
991 } })).toValue(),
992 }, owner_decl_index),
993 .payload => return genTypedValue(bin_file, src_loc, .{
994 .ty = Type.err_int,
995 .val = try mod.intValue(Type.err_int, 0),
996 }, owner_decl_index),
997 }
1291998 }
1292999 },
12931000
......@@ -1306,23 +1013,23 @@ pub fn genTypedValue(
13061013 return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index);
13071014}
13081015
1309pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
1310 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;
1311 const payload_align = payload_ty.abiAlignment(target);
1312 const error_align = Type.anyerror.abiAlignment(target);
1313 if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime()) {
1016pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 {
1017 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0;
1018 const payload_align = payload_ty.abiAlignment(mod);
1019 const error_align = Type.anyerror.abiAlignment(mod);
1020 if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
13141021 return 0;
13151022 } else {
1316 return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(target), payload_align);
1023 return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(mod), payload_align);
13171024 }
13181025}
13191026
1320pub fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u64 {
1321 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;
1322 const payload_align = payload_ty.abiAlignment(target);
1323 const error_align = Type.anyerror.abiAlignment(target);
1324 if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime()) {
1325 return mem.alignForwardGeneric(u64, payload_ty.abiSize(target), error_align);
1027pub fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u64 {
1028 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0;
1029 const payload_align = payload_ty.abiAlignment(mod);
1030 const error_align = Type.anyerror.abiAlignment(mod);
1031 if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1032 return mem.alignForwardGeneric(u64, payload_ty.abiSize(mod), error_align);
13261033 } else {
13271034 return 0;
13281035 }
src/codegen/c.zig+1341-1369
......@@ -16,6 +16,7 @@ const trace = @import("../tracy.zig").trace;
1616const LazySrcLoc = Module.LazySrcLoc;
1717const Air = @import("../Air.zig");
1818const Liveness = @import("../Liveness.zig");
19const InternPool = @import("../InternPool.zig");
1920
2021const BigIntLimb = std.math.big.Limb;
2122const BigInt = std.math.big.int;
......@@ -256,7 +257,7 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) {
256257 return .{ .data = ident };
257258}
258259
259/// This data is available when outputting .c code for a `*Module.Fn`.
260/// This data is available when outputting .c code for a `Module.Fn.Index`.
260261/// It is not available when generating .h file.
261262pub const Function = struct {
262263 air: Air,
......@@ -267,7 +268,7 @@ pub const Function = struct {
267268 next_block_index: usize = 0,
268269 object: Object,
269270 lazy_fns: LazyFnMap,
270 func: *Module.Fn,
271 func_index: Module.Fn.Index,
271272 /// All the locals, to be emitted at the top of the function.
272273 locals: std.ArrayListUnmanaged(Local) = .{},
273274 /// Which locals are available for reuse, based on Type.
......@@ -285,10 +286,11 @@ pub const Function = struct {
285286 const gop = try f.value_map.getOrPut(inst);
286287 if (gop.found_existing) return gop.value_ptr.*;
287288
288 const val = f.air.value(ref).?;
289 const ty = f.air.typeOf(ref);
289 const mod = f.object.dg.module;
290 const val = (try f.air.value(ref, mod)).?;
291 const ty = f.typeOf(ref);
290292
291 const result: CValue = if (lowersToArray(ty, f.object.dg.module.getTarget())) result: {
293 const result: CValue = if (lowersToArray(ty, mod)) result: {
292294 const writer = f.object.code_header.writer();
293295 const alignment = 0;
294296 const decl_c_value = try f.allocLocalValue(ty, alignment);
......@@ -318,11 +320,11 @@ pub const Function = struct {
318320 /// those which go into `allocs`. This function does not add the resulting local into `allocs`;
319321 /// that responsibility lies with the caller.
320322 fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue {
323 const mod = f.object.dg.module;
321324 const gpa = f.object.dg.gpa;
322 const target = f.object.dg.module.getTarget();
323325 try f.locals.append(gpa, .{
324326 .cty_idx = try f.typeToIndex(ty, .complete),
325 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)),
327 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)),
326328 });
327329 return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };
328330 }
......@@ -336,10 +338,10 @@ pub const Function = struct {
336338 /// Only allocates the local; does not print anything. Will attempt to re-use locals, so should
337339 /// not be used for persistent locals (i.e. those in `allocs`).
338340 fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue {
339 const target = f.object.dg.module.getTarget();
341 const mod = f.object.dg.module;
340342 if (f.free_locals_map.getPtr(.{
341343 .cty_idx = try f.typeToIndex(ty, .complete),
342 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)),
344 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod)),
343345 })) |locals_list| {
344346 if (locals_list.popOrNull()) |local_entry| {
345347 return .{ .new_local = local_entry.key };
......@@ -352,8 +354,9 @@ pub const Function = struct {
352354 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
353355 switch (c_value) {
354356 .constant => |inst| {
355 const ty = f.air.typeOf(inst);
356 const val = f.air.value(inst).?;
357 const mod = f.object.dg.module;
358 const ty = f.typeOf(inst);
359 const val = (try f.air.value(inst, mod)).?;
357360 return f.object.dg.renderValue(w, ty, val, location);
358361 },
359362 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
......@@ -364,8 +367,9 @@ pub const Function = struct {
364367 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
365368 switch (c_value) {
366369 .constant => |inst| {
367 const ty = f.air.typeOf(inst);
368 const val = f.air.value(inst).?;
370 const mod = f.object.dg.module;
371 const ty = f.typeOf(inst);
372 const val = (try f.air.value(inst, mod)).?;
369373 try w.writeAll("(*");
370374 try f.object.dg.renderValue(w, ty, val, .Other);
371375 return w.writeByte(')');
......@@ -377,8 +381,9 @@ pub const Function = struct {
377381 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
378382 switch (c_value) {
379383 .constant => |inst| {
380 const ty = f.air.typeOf(inst);
381 const val = f.air.value(inst).?;
384 const mod = f.object.dg.module;
385 const ty = f.typeOf(inst);
386 const val = (try f.air.value(inst, mod)).?;
382387 try f.object.dg.renderValue(w, ty, val, .Other);
383388 try w.writeByte('.');
384389 return f.writeCValue(w, member, .Other);
......@@ -390,8 +395,9 @@ pub const Function = struct {
390395 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
391396 switch (c_value) {
392397 .constant => |inst| {
393 const ty = f.air.typeOf(inst);
394 const val = f.air.value(inst).?;
398 const mod = f.object.dg.module;
399 const ty = f.typeOf(inst);
400 const val = (try f.air.value(inst, mod)).?;
395401 try w.writeByte('(');
396402 try f.object.dg.renderValue(w, ty, val, .Other);
397403 try w.writeAll(")->");
......@@ -446,6 +452,7 @@ pub const Function = struct {
446452 var promoted = f.object.dg.ctypes.promote(gpa);
447453 defer f.object.dg.ctypes.demote(promoted);
448454 const arena = promoted.arena.allocator();
455 const mod = f.object.dg.module;
449456
450457 gop.value_ptr.* = .{
451458 .fn_name = switch (key) {
......@@ -454,12 +461,12 @@ pub const Function = struct {
454461 .never_inline,
455462 => |owner_decl| try std.fmt.allocPrint(arena, "zig_{s}_{}__{d}", .{
456463 @tagName(key),
457 fmtIdent(mem.span(f.object.dg.module.declPtr(owner_decl).name)),
464 fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)),
458465 @enumToInt(owner_decl),
459466 }),
460467 },
461468 .data = switch (key) {
462 .tag_name => .{ .tag_name = try data.tag_name.copy(arena) },
469 .tag_name => .{ .tag_name = data.tag_name },
463470 .never_tail => .{ .never_tail = data.never_tail },
464471 .never_inline => .{ .never_inline = data.never_inline },
465472 },
......@@ -480,6 +487,16 @@ pub const Function = struct {
480487 f.object.dg.ctypes.deinit(gpa);
481488 f.object.dg.fwd_decl.deinit();
482489 }
490
491 fn typeOf(f: *Function, inst: Air.Inst.Ref) Type {
492 const mod = f.object.dg.module;
493 return f.air.typeOf(inst, &mod.intern_pool);
494 }
495
496 fn typeOfIndex(f: *Function, inst: Air.Inst.Index) Type {
497 const mod = f.object.dg.module;
498 return f.air.typeOfIndex(inst, &mod.intern_pool);
499 }
483500};
484501
485502/// This data is available when outputting .c code for a `Module`.
......@@ -508,8 +525,9 @@ pub const DeclGen = struct {
508525
509526 fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
510527 @setCold(true);
528 const mod = dg.module;
511529 const src = LazySrcLoc.nodeOffset(0);
512 const src_loc = src.toSrcLoc(dg.decl.?);
530 const src_loc = src.toSrcLoc(dg.decl.?, mod);
513531 dg.error_msg = try Module.ErrorMsg.create(dg.gpa, src_loc, format, args);
514532 return error.AnalysisFail;
515533 }
......@@ -522,53 +540,28 @@ pub const DeclGen = struct {
522540 decl_index: Decl.Index,
523541 location: ValueRenderLocation,
524542 ) error{ OutOfMemory, AnalysisFail }!void {
525 const decl = dg.module.declPtr(decl_index);
543 const mod = dg.module;
544 const decl = mod.declPtr(decl_index);
526545 assert(decl.has_tv);
527546
528547 // Render an undefined pointer if we have a pointer to a zero-bit or comptime type.
529 if (ty.isPtrAtRuntime() and !decl.ty.isFnOrHasRuntimeBits()) {
548 if (ty.isPtrAtRuntime(mod) and !decl.ty.isFnOrHasRuntimeBits(mod)) {
530549 return dg.writeCValue(writer, .{ .undef = ty });
531550 }
532551
533552 // Chase function values in order to be able to reference the original function.
534 inline for (.{ .function, .extern_fn }) |tag|
535 if (decl.val.castTag(tag)) |func|
536 if (func.data.owner_decl != decl_index)
537 return dg.renderDeclValue(writer, ty, val, func.data.owner_decl, location);
553 if (decl.val.getFunction(mod)) |func| if (func.owner_decl != decl_index)
554 return dg.renderDeclValue(writer, ty, val, func.owner_decl, location);
555 if (decl.val.getExternFunc(mod)) |extern_func| if (extern_func.decl != decl_index)
556 return dg.renderDeclValue(writer, ty, val, extern_func.decl, location);
538557
539 if (decl.val.castTag(.variable)) |var_payload|
540 try dg.renderFwdDecl(decl_index, var_payload.data);
541
542 if (ty.isSlice()) {
543 if (location == .StaticInitializer) {
544 try writer.writeByte('{');
545 } else {
546 try writer.writeByte('(');
547 try dg.renderType(writer, ty);
548 try writer.writeAll("){ .ptr = ");
549 }
550
551 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
552 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), val.slicePtr(), .Initializer);
553
554 var len_pl: Value.Payload.U64 = .{
555 .base = .{ .tag = .int_u64 },
556 .data = val.sliceLen(dg.module),
557 };
558 const len_val = Value.initPayload(&len_pl.base);
559
560 if (location == .StaticInitializer) {
561 return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
562 } else {
563 return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)});
564 }
565 }
558 if (decl.val.getVariable(mod)) |variable| try dg.renderFwdDecl(decl_index, variable);
566559
567560 // We shouldn't cast C function pointers as this is UB (when you call
568561 // them). The analysis until now should ensure that the C function
569562 // pointers are compatible. If they are not, then there is a bug
570563 // somewhere and we should let the C compiler tell us about it.
571 const need_typecast = if (ty.castPtrToFn()) |_| false else !ty.eql(decl.ty, dg.module);
564 const need_typecast = if (ty.castPtrToFn(mod)) |_| false else !ty.childType(mod).eql(decl.ty, mod);
572565 if (need_typecast) {
573566 try writer.writeAll("((");
574567 try dg.renderType(writer, ty);
......@@ -579,127 +572,124 @@ pub const DeclGen = struct {
579572 if (need_typecast) try writer.writeByte(')');
580573 }
581574
582 // Renders a "parent" pointer by recursing to the root decl/variable
583 // that its contents are defined with respect to.
584 //
585 // Used for .elem_ptr, .field_ptr, .opt_payload_ptr, .eu_payload_ptr
586 fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void {
587 if (!ptr_ty.isSlice()) {
588 try writer.writeByte('(');
589 try dg.renderType(writer, ptr_ty);
590 try writer.writeByte(')');
591 }
592 switch (ptr_val.tag()) {
593 .int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}),
594 .decl_ref_mut, .decl_ref, .variable => {
595 const decl_index = switch (ptr_val.tag()) {
596 .decl_ref => ptr_val.castTag(.decl_ref).?.data,
597 .decl_ref_mut => ptr_val.castTag(.decl_ref_mut).?.data.decl_index,
598 .variable => ptr_val.castTag(.variable).?.data.owner_decl,
575 /// Renders a "parent" pointer by recursing to the root decl/variable
576 /// that its contents are defined with respect to.
577 fn renderParentPtr(
578 dg: *DeclGen,
579 writer: anytype,
580 ptr_val: InternPool.Index,
581 location: ValueRenderLocation,
582 ) error{ OutOfMemory, AnalysisFail }!void {
583 const mod = dg.module;
584 const ptr_ty = mod.intern_pool.typeOf(ptr_val).toType();
585 const ptr_cty = try dg.typeToIndex(ptr_ty, .complete);
586 const ptr = mod.intern_pool.indexToKey(ptr_val).ptr;
587 switch (ptr.addr) {
588 .decl, .mut_decl => try dg.renderDeclValue(
589 writer,
590 ptr_ty,
591 ptr_val.toValue(),
592 switch (ptr.addr) {
593 .decl => |decl| decl,
594 .mut_decl => |mut_decl| mut_decl.decl,
595 else => unreachable,
596 },
597 location,
598 ),
599 .int => |int| try writer.print("{x}", .{
600 try dg.fmtIntLiteral(Type.usize, int.toValue(), .Other),
601 }),
602 .eu_payload, .opt_payload => |base| {
603 const ptr_base_ty = mod.intern_pool.typeOf(base).toType();
604 const base_ty = ptr_base_ty.childType(mod);
605 // Ensure complete type definition is visible before accessing fields.
606 _ = try dg.typeToIndex(base_ty, .complete);
607 const payload_ty = switch (ptr.addr) {
608 .eu_payload => base_ty.errorUnionPayload(mod),
609 .opt_payload => base_ty.optionalChild(mod),
599610 else => unreachable,
600611 };
601 try dg.renderDeclValue(writer, ptr_ty, ptr_val, decl_index, location);
612 const ptr_payload_ty = try mod.adjustPtrTypeChild(ptr_base_ty, payload_ty);
613 const ptr_payload_cty = try dg.typeToIndex(ptr_payload_ty, .complete);
614 if (ptr_cty != ptr_payload_cty) {
615 try writer.writeByte('(');
616 try dg.renderCType(writer, ptr_cty);
617 try writer.writeByte(')');
618 }
619 try writer.writeAll("&(");
620 try dg.renderParentPtr(writer, base, location);
621 try writer.writeAll(")->payload");
602622 },
603 .field_ptr => {
604 const target = dg.module.getTarget();
605 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
606
623 .elem => |elem| {
624 const ptr_base_ty = mod.intern_pool.typeOf(elem.base).toType();
625 const elem_ty = ptr_base_ty.elemType2(mod);
626 const ptr_elem_ty = try mod.adjustPtrTypeChild(ptr_base_ty, elem_ty);
627 const ptr_elem_cty = try dg.typeToIndex(ptr_elem_ty, .complete);
628 if (ptr_cty != ptr_elem_cty) {
629 try writer.writeByte('(');
630 try dg.renderCType(writer, ptr_cty);
631 try writer.writeByte(')');
632 }
633 try writer.writeAll("&(");
634 if (mod.intern_pool.indexToKey(ptr_base_ty.toIntern()).ptr_type.flags.size == .One)
635 try writer.writeByte('*');
636 try dg.renderParentPtr(writer, elem.base, location);
637 try writer.print(")[{d}]", .{elem.index});
638 },
639 .field => |field| {
640 const ptr_base_ty = mod.intern_pool.typeOf(field.base).toType();
641 const base_ty = ptr_base_ty.childType(mod);
607642 // Ensure complete type definition is visible before accessing fields.
608 _ = try dg.typeToIndex(field_ptr.container_ty, .complete);
609
610 var container_ptr_pl = ptr_ty.ptrInfo();
611 container_ptr_pl.data.pointee_type = field_ptr.container_ty;
612 const container_ptr_ty = Type.initPayload(&container_ptr_pl.base);
613
614 switch (fieldLocation(
615 field_ptr.container_ty,
616 ptr_ty,
617 @intCast(u32, field_ptr.field_index),
618 target,
619 )) {
620 .begin => try dg.renderParentPtr(
621 writer,
622 field_ptr.container_ptr,
623 container_ptr_ty,
624 location,
625 ),
626 .field => |field| {
643 _ = try dg.typeToIndex(base_ty, .complete);
644 const field_ty = switch (mod.intern_pool.indexToKey(base_ty.toIntern())) {
645 .anon_struct_type, .struct_type, .union_type => base_ty.structFieldType(@intCast(usize, field.index), mod),
646 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
647 .One, .Many, .C => unreachable,
648 .Slice => switch (field.index) {
649 Value.slice_ptr_index => base_ty.slicePtrFieldType(mod),
650 Value.slice_len_index => Type.usize,
651 else => unreachable,
652 },
653 },
654 else => unreachable,
655 };
656 const ptr_field_ty = try mod.adjustPtrTypeChild(ptr_base_ty, field_ty);
657 const ptr_field_cty = try dg.typeToIndex(ptr_field_ty, .complete);
658 if (ptr_cty != ptr_field_cty) {
659 try writer.writeByte('(');
660 try dg.renderCType(writer, ptr_cty);
661 try writer.writeByte(')');
662 }
663 switch (fieldLocation(base_ty, ptr_ty, @intCast(u32, field.index), mod)) {
664 .begin => try dg.renderParentPtr(writer, field.base, location),
665 .field => |name| {
627666 try writer.writeAll("&(");
628 try dg.renderParentPtr(
629 writer,
630 field_ptr.container_ptr,
631 container_ptr_ty,
632 location,
633 );
667 try dg.renderParentPtr(writer, field.base, location);
634668 try writer.writeAll(")->");
635 try dg.writeCValue(writer, field);
669 try dg.writeCValue(writer, name);
636670 },
637671 .byte_offset => |byte_offset| {
638 var u8_ptr_pl = ptr_ty.ptrInfo();
639 u8_ptr_pl.data.pointee_type = Type.u8;
640 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
641
642 var byte_offset_pl = Value.Payload.U64{
643 .base = .{ .tag = .int_u64 },
644 .data = byte_offset,
645 };
646 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
672 const u8_ptr_ty = try mod.adjustPtrTypeChild(ptr_ty, Type.u8);
673 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
647674
648675 try writer.writeAll("((");
649676 try dg.renderType(writer, u8_ptr_ty);
650677 try writer.writeByte(')');
651 try dg.renderParentPtr(
652 writer,
653 field_ptr.container_ptr,
654 container_ptr_ty,
655 location,
656 );
678 try dg.renderParentPtr(writer, field.base, location);
657679 try writer.print(" + {})", .{
658680 try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other),
659681 });
660682 },
661683 .end => {
662684 try writer.writeAll("((");
663 try dg.renderParentPtr(
664 writer,
665 field_ptr.container_ptr,
666 container_ptr_ty,
667 location,
668 );
685 try dg.renderParentPtr(writer, field.base, location);
669686 try writer.print(") + {})", .{
670 try dg.fmtIntLiteral(Type.usize, Value.one, .Other),
687 try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other),
671688 });
672689 },
673690 }
674691 },
675 .elem_ptr => {
676 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
677 var elem_ptr_ty_pl: Type.Payload.ElemType = .{
678 .base = .{ .tag = .c_mut_pointer },
679 .data = elem_ptr.elem_ty,
680 };
681 const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);
682
683 try writer.writeAll("&(");
684 try dg.renderParentPtr(writer, elem_ptr.array_ptr, elem_ptr_ty, location);
685 try writer.print(")[{d}]", .{elem_ptr.index});
686 },
687 .opt_payload_ptr, .eu_payload_ptr => {
688 const payload_ptr = ptr_val.cast(Value.Payload.PayloadPtr).?.data;
689 var container_ptr_ty_pl: Type.Payload.ElemType = .{
690 .base = .{ .tag = .c_mut_pointer },
691 .data = payload_ptr.container_ty,
692 };
693 const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);
694
695 // Ensure complete type definition is visible before accessing fields.
696 _ = try dg.typeToIndex(payload_ptr.container_ty, .complete);
697
698 try writer.writeAll("&(");
699 try dg.renderParentPtr(writer, payload_ptr.container_ptr, container_ptr_ty, location);
700 try writer.writeAll(")->payload");
701 },
702 else => unreachable,
692 .comptime_field => unreachable,
703693 }
704694 }
705695
......@@ -710,23 +700,25 @@ pub const DeclGen = struct {
710700 arg_val: Value,
711701 location: ValueRenderLocation,
712702 ) error{ OutOfMemory, AnalysisFail }!void {
703 const mod = dg.module;
713704 var val = arg_val;
714 if (val.castTag(.runtime_value)) |rt| {
715 val = rt.data;
705 switch (mod.intern_pool.indexToKey(val.ip_index)) {
706 .runtime_value => |rt| val = rt.val.toValue(),
707 else => {},
716708 }
717 const target = dg.module.getTarget();
709 const target = mod.getTarget();
718710 const initializer_type: ValueRenderLocation = switch (location) {
719711 .StaticInitializer => .StaticInitializer,
720712 else => .Initializer,
721713 };
722714
723 const safety_on = switch (dg.module.optimizeMode()) {
715 const safety_on = switch (mod.optimizeMode()) {
724716 .Debug, .ReleaseSafe => true,
725717 .ReleaseFast, .ReleaseSmall => false,
726718 };
727719
728 if (val.isUndefDeep()) {
729 switch (ty.zigTypeTag()) {
720 if (val.isUndefDeep(mod)) {
721 switch (ty.zigTypeTag(mod)) {
730722 .Bool => {
731723 if (safety_on) {
732724 return writer.writeAll("0xaa");
......@@ -737,8 +729,8 @@ pub const DeclGen = struct {
737729 .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}),
738730 .Float => {
739731 const bits = ty.floatBits(target);
740 var repr_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = bits };
741 const repr_ty = Type.initPayload(&repr_pl.base);
732 // All unsigned ints matching float types are pre-allocated.
733 const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
742734
743735 try writer.writeAll("zig_cast_");
744736 try dg.renderTypeForBuiltinFnName(writer, ty);
......@@ -757,7 +749,7 @@ pub const DeclGen = struct {
757749 try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument);
758750 return writer.writeByte(')');
759751 },
760 .Pointer => if (ty.isSlice()) {
752 .Pointer => if (ty.isSlice(mod)) {
761753 if (!location.isInitializer()) {
762754 try writer.writeByte('(');
763755 try dg.renderType(writer, ty);
......@@ -765,8 +757,7 @@ pub const DeclGen = struct {
765757 }
766758
767759 try writer.writeAll("{(");
768 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
769 const ptr_ty = ty.slicePtrFieldType(&buf);
760 const ptr_ty = ty.slicePtrFieldType(mod);
770761 try dg.renderType(writer, ptr_ty);
771762 return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
772763 } else {
......@@ -775,14 +766,13 @@ pub const DeclGen = struct {
775766 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
776767 },
777768 .Optional => {
778 var opt_buf: Type.Payload.ElemType = undefined;
779 const payload_ty = ty.optionalChild(&opt_buf);
769 const payload_ty = ty.optionalChild(mod);
780770
781 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
771 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
782772 return dg.renderValue(writer, Type.bool, val, location);
783773 }
784774
785 if (ty.optionalReprIsPayload()) {
775 if (ty.optionalReprIsPayload(mod)) {
786776 return dg.renderValue(writer, payload_ty, val, location);
787777 }
788778
......@@ -798,7 +788,7 @@ pub const DeclGen = struct {
798788 try dg.renderValue(writer, Type.bool, val, initializer_type);
799789 return writer.writeAll(" }");
800790 },
801 .Struct => switch (ty.containerLayout()) {
791 .Struct => switch (ty.containerLayout(mod)) {
802792 .Auto, .Extern => {
803793 if (!location.isInitializer()) {
804794 try writer.writeByte('(');
......@@ -808,10 +798,10 @@ pub const DeclGen = struct {
808798
809799 try writer.writeByte('{');
810800 var empty = true;
811 for (0..ty.structFieldCount()) |field_i| {
812 if (ty.structFieldIsComptime(field_i)) continue;
813 const field_ty = ty.structFieldType(field_i);
814 if (!field_ty.hasRuntimeBits()) continue;
801 for (0..ty.structFieldCount(mod)) |field_i| {
802 if (ty.structFieldIsComptime(field_i, mod)) continue;
803 const field_ty = ty.structFieldType(field_i, mod);
804 if (!field_ty.hasRuntimeBits(mod)) continue;
815805
816806 if (!empty) try writer.writeByte(',');
817807 try dg.renderValue(writer, field_ty, val, initializer_type);
......@@ -831,29 +821,29 @@ pub const DeclGen = struct {
831821 }
832822
833823 try writer.writeByte('{');
834 if (ty.unionTagTypeSafety()) |tag_ty| {
835 const layout = ty.unionGetLayout(target);
824 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
825 const layout = ty.unionGetLayout(mod);
836826 if (layout.tag_size != 0) {
837827 try writer.writeAll(" .tag = ");
838828 try dg.renderValue(writer, tag_ty, val, initializer_type);
839829 }
840 if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}');
830 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
841831 if (layout.tag_size != 0) try writer.writeByte(',');
842832 try writer.writeAll(" .payload = {");
843833 }
844 for (ty.unionFields().values()) |field| {
845 if (!field.ty.hasRuntimeBits()) continue;
834 for (ty.unionFields(mod).values()) |field| {
835 if (!field.ty.hasRuntimeBits(mod)) continue;
846836 try dg.renderValue(writer, field.ty, val, initializer_type);
847837 break;
848838 }
849 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
839 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
850840 return writer.writeByte('}');
851841 },
852842 .ErrorUnion => {
853 const payload_ty = ty.errorUnionPayload();
854 const error_ty = ty.errorUnionSet();
843 const payload_ty = ty.errorUnionPayload(mod);
844 const error_ty = ty.errorUnionSet(mod);
855845
856 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
846 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
857847 return dg.renderValue(writer, error_ty, val, location);
858848 }
859849
......@@ -870,11 +860,11 @@ pub const DeclGen = struct {
870860 return writer.writeAll(" }");
871861 },
872862 .Array, .Vector => {
873 const ai = ty.arrayInfo();
874 if (ai.elem_type.eql(Type.u8, dg.module)) {
863 const ai = ty.arrayInfo(mod);
864 if (ai.elem_type.eql(Type.u8, mod)) {
875865 var literal = stringLiteral(writer);
876866 try literal.start();
877 const c_len = ty.arrayLenIncludingSentinel();
867 const c_len = ty.arrayLenIncludingSentinel(mod);
878868 var index: u64 = 0;
879869 while (index < c_len) : (index += 1)
880870 try literal.writeChar(0xaa);
......@@ -887,11 +877,11 @@ pub const DeclGen = struct {
887877 }
888878
889879 try writer.writeByte('{');
890 const c_len = ty.arrayLenIncludingSentinel();
880 const c_len = ty.arrayLenIncludingSentinel(mod);
891881 var index: u64 = 0;
892882 while (index < c_len) : (index += 1) {
893883 if (index > 0) try writer.writeAll(", ");
894 try dg.renderValue(writer, ty.childType(), val, initializer_type);
884 try dg.renderValue(writer, ty.childType(mod), val, initializer_type);
895885 }
896886 return writer.writeByte('}');
897887 }
......@@ -916,23 +906,129 @@ pub const DeclGen = struct {
916906 }
917907 unreachable;
918908 }
919 switch (ty.zigTypeTag()) {
920 .Int => switch (val.tag()) {
921 .field_ptr,
922 .elem_ptr,
923 .opt_payload_ptr,
924 .eu_payload_ptr,
925 .decl_ref_mut,
926 .decl_ref,
927 => try dg.renderParentPtr(writer, val, ty, location),
928 else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
909
910 switch (mod.intern_pool.indexToKey(val.ip_index)) {
911 // types, not values
912 .int_type,
913 .ptr_type,
914 .array_type,
915 .vector_type,
916 .opt_type,
917 .anyframe_type,
918 .error_union_type,
919 .simple_type,
920 .struct_type,
921 .anon_struct_type,
922 .union_type,
923 .opaque_type,
924 .enum_type,
925 .func_type,
926 .error_set_type,
927 .inferred_error_set_type,
928 // memoization, not values
929 .memoized_call,
930 => unreachable,
931
932 .undef, .runtime_value => unreachable, // handled above
933 .simple_value => |simple_value| switch (simple_value) {
934 // non-runtime values
935 .undefined => unreachable,
936 .void => unreachable,
937 .null => unreachable,
938 .empty_struct => unreachable,
939 .@"unreachable" => unreachable,
940 .generic_poison => unreachable,
941
942 .false => try writer.writeAll("false"),
943 .true => try writer.writeAll("true"),
929944 },
930 .Float => {
945 .variable,
946 .extern_func,
947 .func,
948 .enum_literal,
949 .empty_enum_value,
950 => unreachable, // non-runtime values
951 .int => |int| switch (int.storage) {
952 .u64, .i64, .big_int => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}),
953 .lazy_align, .lazy_size => {
954 try writer.writeAll("((");
955 try dg.renderType(writer, ty);
956 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
957 },
958 },
959 .err => |err| try writer.print("zig_error_{}", .{
960 fmtIdent(mod.intern_pool.stringToSlice(err.name)),
961 }),
962 .error_union => |error_union| {
963 const payload_ty = ty.errorUnionPayload(mod);
964 const error_ty = ty.errorUnionSet(mod);
965 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
966 switch (error_union.val) {
967 .err_name => |err_name| return dg.renderValue(
968 writer,
969 error_ty,
970 (try mod.intern(.{ .err = .{
971 .ty = error_ty.toIntern(),
972 .name = err_name,
973 } })).toValue(),
974 location,
975 ),
976 .payload => return dg.renderValue(
977 writer,
978 Type.err_int,
979 try mod.intValue(Type.err_int, 0),
980 location,
981 ),
982 }
983 }
984
985 if (!location.isInitializer()) {
986 try writer.writeByte('(');
987 try dg.renderType(writer, ty);
988 try writer.writeByte(')');
989 }
990
991 try writer.writeAll("{ .payload = ");
992 try dg.renderValue(
993 writer,
994 payload_ty,
995 switch (error_union.val) {
996 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
997 .payload => |payload| payload,
998 }.toValue(),
999 initializer_type,
1000 );
1001 try writer.writeAll(", .error = ");
1002 switch (error_union.val) {
1003 .err_name => |err_name| try dg.renderValue(
1004 writer,
1005 error_ty,
1006 (try mod.intern(.{ .err = .{
1007 .ty = error_ty.toIntern(),
1008 .name = err_name,
1009 } })).toValue(),
1010 location,
1011 ),
1012 .payload => try dg.renderValue(
1013 writer,
1014 Type.err_int,
1015 try mod.intValue(Type.err_int, 0),
1016 location,
1017 ),
1018 }
1019 try writer.writeAll(" }");
1020 },
1021 .enum_tag => {
1022 const enum_tag = mod.intern_pool.indexToKey(val.ip_index).enum_tag;
1023 const int_tag_ty = mod.intern_pool.typeOf(enum_tag.int);
1024 try dg.renderValue(writer, int_tag_ty.toType(), enum_tag.int.toValue(), location);
1025 },
1026 .float => {
9311027 const bits = ty.floatBits(target);
932 const f128_val = val.toFloat(f128);
1028 const f128_val = val.toFloat(f128, mod);
9331029
934 var repr_ty_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = bits };
935 const repr_ty = Type.initPayload(&repr_ty_pl.base);
1030 // All unsigned ints matching float types are pre-allocated.
1031 const repr_ty = mod.intType(.unsigned, bits) catch unreachable;
9361032
9371033 assert(bits <= 128);
9381034 var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined;
......@@ -943,21 +1039,15 @@ pub const DeclGen = struct {
9431039 };
9441040
9451041 switch (bits) {
946 16 => repr_val_big.set(@bitCast(u16, val.toFloat(f16))),
947 32 => repr_val_big.set(@bitCast(u32, val.toFloat(f32))),
948 64 => repr_val_big.set(@bitCast(u64, val.toFloat(f64))),
949 80 => repr_val_big.set(@bitCast(u80, val.toFloat(f80))),
1042 16 => repr_val_big.set(@bitCast(u16, val.toFloat(f16, mod))),
1043 32 => repr_val_big.set(@bitCast(u32, val.toFloat(f32, mod))),
1044 64 => repr_val_big.set(@bitCast(u64, val.toFloat(f64, mod))),
1045 80 => repr_val_big.set(@bitCast(u80, val.toFloat(f80, mod))),
9501046 128 => repr_val_big.set(@bitCast(u128, f128_val)),
9511047 else => unreachable,
9521048 }
9531049
954 var repr_val_pl = Value.Payload.BigInt{
955 .base = .{
956 .tag = if (repr_val_big.positive) .int_big_positive else .int_big_negative,
957 },
958 .data = repr_val_big.limbs[0..repr_val_big.len],
959 };
960 const repr_val = Value.initPayload(&repr_val_pl.base);
1050 const repr_val = try mod.intValue_big(repr_ty, repr_val_big.toConst());
9611051
9621052 try writer.writeAll("zig_cast_");
9631053 try dg.renderTypeForBuiltinFnName(writer, ty);
......@@ -968,10 +1058,10 @@ pub const DeclGen = struct {
9681058 try dg.renderTypeForBuiltinFnName(writer, ty);
9691059 try writer.writeByte('(');
9701060 switch (bits) {
971 16 => try writer.print("{x}", .{val.toFloat(f16)}),
972 32 => try writer.print("{x}", .{val.toFloat(f32)}),
973 64 => try writer.print("{x}", .{val.toFloat(f64)}),
974 80 => try writer.print("{x}", .{val.toFloat(f80)}),
1061 16 => try writer.print("{x}", .{val.toFloat(f16, mod)}),
1062 32 => try writer.print("{x}", .{val.toFloat(f32, mod)}),
1063 64 => try writer.print("{x}", .{val.toFloat(f64, mod)}),
1064 80 => try writer.print("{x}", .{val.toFloat(f80, mod)}),
9751065 128 => try writer.print("{x}", .{f128_val}),
9761066 else => unreachable,
9771067 }
......@@ -1011,10 +1101,10 @@ pub const DeclGen = struct {
10111101 if (std.math.isNan(f128_val)) switch (bits) {
10121102 // We only actually need to pass the significand, but it will get
10131103 // properly masked anyway, so just pass the whole value.
1014 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16))}),
1015 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32))}),
1016 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64))}),
1017 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80))}),
1104 16 => try writer.print("\"0x{x}\"", .{@bitCast(u16, val.toFloat(f16, mod))}),
1105 32 => try writer.print("\"0x{x}\"", .{@bitCast(u32, val.toFloat(f32, mod))}),
1106 64 => try writer.print("\"0x{x}\"", .{@bitCast(u64, val.toFloat(f64, mod))}),
1107 80 => try writer.print("\"0x{x}\"", .{@bitCast(u80, val.toFloat(f80, mod))}),
10181108 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}),
10191109 else => unreachable,
10201110 };
......@@ -1023,173 +1113,80 @@ pub const DeclGen = struct {
10231113 }
10241114 try writer.print("{x}", .{try dg.fmtIntLiteral(repr_ty, repr_val, location)});
10251115 if (!empty) try writer.writeByte(')');
1026 return;
10271116 },
1028 .Pointer => switch (val.tag()) {
1029 .null_value, .zero => if (ty.isSlice()) {
1030 var slice_pl = Value.Payload.Slice{
1031 .base = .{ .tag = .slice },
1032 .data = .{ .ptr = val, .len = Value.undef },
1033 };
1034 const slice_val = Value.initPayload(&slice_pl.base);
1035
1036 return dg.renderValue(writer, ty, slice_val, location);
1037 } else {
1038 try writer.writeAll("((");
1039 try dg.renderType(writer, ty);
1040 try writer.writeAll(")NULL)");
1041 },
1042 .variable => {
1043 const decl = val.castTag(.variable).?.data.owner_decl;
1044 return dg.renderDeclValue(writer, ty, val, decl, location);
1045 },
1046 .slice => {
1117 .ptr => |ptr| {
1118 if (ptr.len != .none) {
10471119 if (!location.isInitializer()) {
10481120 try writer.writeByte('(');
10491121 try dg.renderType(writer, ty);
10501122 try writer.writeByte(')');
10511123 }
1052
1053 const slice = val.castTag(.slice).?.data;
1054 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1055
10561124 try writer.writeByte('{');
1057 try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type);
1058 try writer.writeAll(", ");
1059 try dg.renderValue(writer, Type.usize, slice.len, initializer_type);
1060 try writer.writeByte('}');
1061 },
1062 .function => {
1063 const func = val.castTag(.function).?.data;
1064 try dg.renderDeclName(writer, func.owner_decl, 0);
1065 },
1066 .extern_fn => {
1067 const extern_fn = val.castTag(.extern_fn).?.data;
1068 try dg.renderDeclName(writer, extern_fn.owner_decl, 0);
1069 },
1070 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
1071 try writer.writeAll("((");
1072 try dg.renderType(writer, ty);
1073 return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)});
1074 },
1075 .field_ptr,
1076 .elem_ptr,
1077 .opt_payload_ptr,
1078 .eu_payload_ptr,
1079 .decl_ref_mut,
1080 .decl_ref,
1081 => try dg.renderParentPtr(writer, val, ty, location),
1082 else => unreachable,
1083 },
1084 .Array, .Vector => {
1085 if (location == .FunctionArgument) {
1086 try writer.writeByte('(');
1087 try dg.renderType(writer, ty);
1088 try writer.writeByte(')');
10891125 }
1090
1091 // First try specific tag representations for more efficiency.
1092 switch (val.tag()) {
1093 .undef, .empty_struct_value, .empty_array => {
1094 const ai = ty.arrayInfo();
1095 try writer.writeByte('{');
1096 if (ai.sentinel) |s| {
1097 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1098 } else {
1099 try writer.writeByte('0');
1100 }
1101 try writer.writeByte('}');
1102 },
1103 .bytes, .str_lit => |t| {
1104 const bytes = switch (t) {
1105 .bytes => val.castTag(.bytes).?.data,
1106 .str_lit => bytes: {
1107 const str_lit = val.castTag(.str_lit).?.data;
1108 break :bytes dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
1109 },
1126 const ptr_location = switch (ptr.len) {
1127 .none => location,
1128 else => initializer_type,
1129 };
1130 const ptr_ty = switch (ptr.len) {
1131 .none => ty,
1132 else => ty.slicePtrFieldType(mod),
1133 };
1134 const ptr_val = switch (ptr.len) {
1135 .none => val,
1136 else => val.slicePtr(mod),
1137 };
1138 switch (ptr.addr) {
1139 .decl, .mut_decl => try dg.renderDeclValue(
1140 writer,
1141 ptr_ty,
1142 ptr_val,
1143 switch (ptr.addr) {
1144 .decl => |decl| decl,
1145 .mut_decl => |mut_decl| mut_decl.decl,
11101146 else => unreachable,
1111 };
1112 const sentinel = if (ty.sentinel()) |sentinel| @intCast(u8, sentinel.toUnsignedInt(target)) else null;
1113 try writer.print("{s}", .{
1114 fmtStringLiteral(bytes[0..@intCast(usize, ty.arrayLen())], sentinel),
1147 },
1148 ptr_location,
1149 ),
1150 .int => |int| {
1151 try writer.writeAll("((");
1152 try dg.renderType(writer, ptr_ty);
1153 try writer.print("){x})", .{
1154 try dg.fmtIntLiteral(Type.usize, int.toValue(), ptr_location),
11151155 });
11161156 },
1117 else => {
1118 // Fall back to generic implementation.
1119 var arena = std.heap.ArenaAllocator.init(dg.gpa);
1120 defer arena.deinit();
1121 const arena_allocator = arena.allocator();
1122
1123 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal
1124 const max_string_initializer_len = 65535;
1125
1126 const ai = ty.arrayInfo();
1127 if (ai.elem_type.eql(Type.u8, dg.module)) {
1128 if (ai.len <= max_string_initializer_len) {
1129 var literal = stringLiteral(writer);
1130 try literal.start();
1131 var index: usize = 0;
1132 while (index < ai.len) : (index += 1) {
1133 const elem_val = try val.elemValue(dg.module, arena_allocator, index);
1134 const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target));
1135 try literal.writeChar(elem_val_u8);
1136 }
1137 if (ai.sentinel) |s| {
1138 const s_u8 = @intCast(u8, s.toUnsignedInt(target));
1139 if (s_u8 != 0) try literal.writeChar(s_u8);
1140 }
1141 try literal.end();
1142 } else {
1143 try writer.writeByte('{');
1144 var index: usize = 0;
1145 while (index < ai.len) : (index += 1) {
1146 if (index != 0) try writer.writeByte(',');
1147 const elem_val = try val.elemValue(dg.module, arena_allocator, index);
1148 const elem_val_u8 = if (elem_val.isUndef()) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(target));
1149 try writer.print("'\\x{x}'", .{elem_val_u8});
1150 }
1151 if (ai.sentinel) |s| {
1152 if (index != 0) try writer.writeByte(',');
1153 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1154 }
1155 try writer.writeByte('}');
1156 }
1157 } else {
1158 try writer.writeByte('{');
1159 var index: usize = 0;
1160 while (index < ai.len) : (index += 1) {
1161 if (index != 0) try writer.writeByte(',');
1162 const elem_val = try val.elemValue(dg.module, arena_allocator, index);
1163 try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type);
1164 }
1165 if (ai.sentinel) |s| {
1166 if (index != 0) try writer.writeByte(',');
1167 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1168 }
1169 try writer.writeByte('}');
1170 }
1171 },
1157 .eu_payload,
1158 .opt_payload,
1159 .elem,
1160 .field,
1161 => try dg.renderParentPtr(writer, ptr_val.ip_index, ptr_location),
1162 .comptime_field => unreachable,
11721163 }
1173 },
1174 .Bool => {
1175 if (val.toBool()) {
1176 return writer.writeAll("true");
1177 } else {
1178 return writer.writeAll("false");
1164 if (ptr.len != .none) {
1165 try writer.writeAll(", ");
1166 try dg.renderValue(writer, Type.usize, ptr.len.toValue(), initializer_type);
1167 try writer.writeByte('}');
11791168 }
11801169 },
1181 .Optional => {
1182 var opt_buf: Type.Payload.ElemType = undefined;
1183 const payload_ty = ty.optionalChild(&opt_buf);
1170 .opt => |opt| {
1171 const payload_ty = ty.optionalChild(mod);
11841172
1185 const is_null_val = Value.makeBool(val.tag() == .null_value);
1186 if (!payload_ty.hasRuntimeBitsIgnoreComptime())
1173 const is_null_val = Value.makeBool(opt.val == .none);
1174 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
11871175 return dg.renderValue(writer, Type.bool, is_null_val, location);
11881176
1189 if (ty.optionalReprIsPayload()) {
1190 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else val;
1191 return dg.renderValue(writer, payload_ty, payload_val, location);
1192 }
1177 if (ty.optionalReprIsPayload(mod)) return dg.renderValue(
1178 writer,
1179 payload_ty,
1180 switch (opt.val) {
1181 .none => switch (payload_ty.zigTypeTag(mod)) {
1182 .ErrorSet => try mod.intValue(Type.err_int, 0),
1183 .Pointer => try mod.getCoerced(val, payload_ty),
1184 else => unreachable,
1185 },
1186 else => |payload| payload.toValue(),
1187 },
1188 location,
1189 );
11931190
11941191 if (!location.isInitializer()) {
11951192 try writer.writeByte('(');
......@@ -1197,93 +1194,74 @@ pub const DeclGen = struct {
11971194 try writer.writeByte(')');
11981195 }
11991196
1200 const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef;
1201
12021197 try writer.writeAll("{ .payload = ");
1203 try dg.renderValue(writer, payload_ty, payload_val, initializer_type);
1198 try dg.renderValue(writer, payload_ty, switch (opt.val) {
1199 .none => try mod.intern(.{ .undef = payload_ty.ip_index }),
1200 else => |payload| payload,
1201 }.toValue(), initializer_type);
12041202 try writer.writeAll(", .is_null = ");
12051203 try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
12061204 try writer.writeAll(" }");
12071205 },
1208 .ErrorSet => {
1209 if (val.castTag(.@"error")) |error_pl| {
1210 // Error values are already defined by genErrDecls.
1211 try writer.print("zig_error_{}", .{fmtIdent(error_pl.data.name)});
1212 } else {
1213 try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, .Other)});
1214 }
1215 },
1216 .ErrorUnion => {
1217 const payload_ty = ty.errorUnionPayload();
1218 const error_ty = ty.errorUnionSet();
1219 const error_val = if (val.errorUnionIsPayload()) Value.zero else val;
1206 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1207 .array_type, .vector_type => {
1208 if (location == .FunctionArgument) {
1209 try writer.writeByte('(');
1210 try dg.renderType(writer, ty);
1211 try writer.writeByte(')');
1212 }
1213 // Fall back to generic implementation.
12201214
1221 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1222 return dg.renderValue(writer, error_ty, error_val, location);
1223 }
1215 // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal
1216 const max_string_initializer_len = 65535;
12241217
1225 if (!location.isInitializer()) {
1226 try writer.writeByte('(');
1227 try dg.renderType(writer, ty);
1228 try writer.writeByte(')');
1229 }
1230
1231 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.undef;
1232 try writer.writeAll("{ .payload = ");
1233 try dg.renderValue(writer, payload_ty, payload_val, initializer_type);
1234 try writer.writeAll(", .error = ");
1235 try dg.renderValue(writer, error_ty, error_val, initializer_type);
1236 try writer.writeAll(" }");
1237 },
1238 .Enum => {
1239 switch (val.tag()) {
1240 .enum_field_index => {
1241 const field_index = val.castTag(.enum_field_index).?.data;
1242 switch (ty.tag()) {
1243 .enum_simple => return writer.print("{d}", .{field_index}),
1244 .enum_full, .enum_nonexhaustive => {
1245 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
1246 if (enum_full.values.count() != 0) {
1247 const tag_val = enum_full.values.keys()[field_index];
1248 return dg.renderValue(writer, enum_full.tag_ty, tag_val, location);
1249 } else {
1250 return writer.print("{d}", .{field_index});
1251 }
1252 },
1253 .enum_numbered => {
1254 const enum_obj = ty.castTag(.enum_numbered).?.data;
1255 if (enum_obj.values.count() != 0) {
1256 const tag_val = enum_obj.values.keys()[field_index];
1257 return dg.renderValue(writer, enum_obj.tag_ty, tag_val, location);
1258 } else {
1259 return writer.print("{d}", .{field_index});
1260 }
1261 },
1262 else => unreachable,
1218 const ai = ty.arrayInfo(mod);
1219 if (ai.elem_type.eql(Type.u8, mod)) {
1220 if (ai.len <= max_string_initializer_len) {
1221 var literal = stringLiteral(writer);
1222 try literal.start();
1223 var index: usize = 0;
1224 while (index < ai.len) : (index += 1) {
1225 const elem_val = try val.elemValue(mod, index);
1226 const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod));
1227 try literal.writeChar(elem_val_u8);
1228 }
1229 if (ai.sentinel) |s| {
1230 const s_u8 = @intCast(u8, s.toUnsignedInt(mod));
1231 if (s_u8 != 0) try literal.writeChar(s_u8);
1232 }
1233 try literal.end();
1234 } else {
1235 try writer.writeByte('{');
1236 var index: usize = 0;
1237 while (index < ai.len) : (index += 1) {
1238 if (index != 0) try writer.writeByte(',');
1239 const elem_val = try val.elemValue(mod, index);
1240 const elem_val_u8 = if (elem_val.isUndef(mod)) undefPattern(u8) else @intCast(u8, elem_val.toUnsignedInt(mod));
1241 try writer.print("'\\x{x}'", .{elem_val_u8});
1242 }
1243 if (ai.sentinel) |s| {
1244 if (index != 0) try writer.writeByte(',');
1245 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1246 }
1247 try writer.writeByte('}');
12631248 }
1264 },
1265 else => {
1266 var int_tag_ty_buffer: Type.Payload.Bits = undefined;
1267 const int_tag_ty = ty.intTagType(&int_tag_ty_buffer);
1268 return dg.renderValue(writer, int_tag_ty, val, location);
1269 },
1270 }
1271 },
1272 .Fn => switch (val.tag()) {
1273 .function => {
1274 const decl = val.castTag(.function).?.data.owner_decl;
1275 return dg.renderDeclValue(writer, ty, val, decl, location);
1276 },
1277 .extern_fn => {
1278 const decl = val.castTag(.extern_fn).?.data.owner_decl;
1279 return dg.renderDeclValue(writer, ty, val, decl, location);
1249 } else {
1250 try writer.writeByte('{');
1251 var index: usize = 0;
1252 while (index < ai.len) : (index += 1) {
1253 if (index != 0) try writer.writeByte(',');
1254 const elem_val = try val.elemValue(mod, index);
1255 try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type);
1256 }
1257 if (ai.sentinel) |s| {
1258 if (index != 0) try writer.writeByte(',');
1259 try dg.renderValue(writer, ai.elem_type, s, initializer_type);
1260 }
1261 try writer.writeByte('}');
1262 }
12801263 },
1281 else => unreachable,
1282 },
1283 .Struct => switch (ty.containerLayout()) {
1284 .Auto, .Extern => {
1285 const field_vals = val.castTag(.aggregate).?.data;
1286
1264 .anon_struct_type => |tuple| {
12871265 if (!location.isInitializer()) {
12881266 try writer.writeByte('(');
12891267 try dg.renderType(writer, ty);
......@@ -1292,133 +1270,184 @@ pub const DeclGen = struct {
12921270
12931271 try writer.writeByte('{');
12941272 var empty = true;
1295 for (field_vals, 0..) |field_val, field_i| {
1296 if (ty.structFieldIsComptime(field_i)) continue;
1297 const field_ty = ty.structFieldType(field_i);
1298 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1273 for (tuple.types, tuple.values, 0..) |field_ty, comptime_ty, field_i| {
1274 if (comptime_ty != .none) continue;
1275 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
12991276
13001277 if (!empty) try writer.writeByte(',');
1301 try dg.renderValue(writer, field_ty, field_val, initializer_type);
1278
1279 const field_val = switch (aggregate.storage) {
1280 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1281 .ty = field_ty,
1282 .storage = .{ .u64 = bytes[field_i] },
1283 } }),
1284 .elems => |elems| elems[field_i],
1285 .repeated_elem => |elem| elem,
1286 };
1287 try dg.renderValue(writer, field_ty.toType(), field_val.toValue(), initializer_type);
13021288
13031289 empty = false;
13041290 }
13051291 try writer.writeByte('}');
13061292 },
1307 .Packed => {
1308 const field_vals = val.castTag(.aggregate).?.data;
1309 const int_info = ty.intInfo(target);
1293 .struct_type => |struct_type| {
1294 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1295 switch (struct_obj.layout) {
1296 .Auto, .Extern => {
1297 if (!location.isInitializer()) {
1298 try writer.writeByte('(');
1299 try dg.renderType(writer, ty);
1300 try writer.writeByte(')');
1301 }
13101302
1311 var bit_offset_ty_pl = Type.Payload.Bits{
1312 .base = .{ .tag = .int_unsigned },
1313 .data = Type.smallestUnsignedBits(int_info.bits - 1),
1314 };
1315 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
1303 try writer.writeByte('{');
1304 var empty = true;
1305 for (struct_obj.fields.values(), 0..) |field, field_i| {
1306 if (field.is_comptime) continue;
1307 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1308
1309 if (!empty) try writer.writeByte(',');
1310 const field_val = switch (aggregate.storage) {
1311 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1312 .ty = field.ty.toIntern(),
1313 .storage = .{ .u64 = bytes[field_i] },
1314 } }),
1315 .elems => |elems| elems[field_i],
1316 .repeated_elem => |elem| elem,
1317 };
1318 try dg.renderValue(writer, field.ty, field_val.toValue(), initializer_type);
1319
1320 empty = false;
1321 }
1322 try writer.writeByte('}');
1323 },
1324 .Packed => {
1325 const int_info = ty.intInfo(mod);
13161326
1317 var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 };
1318 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
1327 const bits = Type.smallestUnsignedBits(int_info.bits - 1);
1328 const bit_offset_ty = try mod.intType(.unsigned, bits);
13191329
1320 var eff_num_fields: usize = 0;
1321 for (0..field_vals.len) |field_i| {
1322 if (ty.structFieldIsComptime(field_i)) continue;
1323 const field_ty = ty.structFieldType(field_i);
1324 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1330 var bit_offset: u64 = 0;
1331 var eff_num_fields: usize = 0;
13251332
1326 eff_num_fields += 1;
1327 }
1333 for (struct_obj.fields.values()) |field| {
1334 if (field.is_comptime) continue;
1335 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
13281336
1329 if (eff_num_fields == 0) {
1330 try writer.writeByte('(');
1331 try dg.renderValue(writer, ty, Value.undef, initializer_type);
1332 try writer.writeByte(')');
1333 } else if (ty.bitSize(target) > 64) {
1334 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
1335 var num_or = eff_num_fields - 1;
1336 while (num_or > 0) : (num_or -= 1) {
1337 try writer.writeAll("zig_or_");
1338 try dg.renderTypeForBuiltinFnName(writer, ty);
1339 try writer.writeByte('(');
1340 }
1337 eff_num_fields += 1;
1338 }
13411339
1342 var eff_index: usize = 0;
1343 var needs_closing_paren = false;
1344 for (field_vals, 0..) |field_val, field_i| {
1345 if (ty.structFieldIsComptime(field_i)) continue;
1346 const field_ty = ty.structFieldType(field_i);
1347 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1348
1349 const cast_context = IntCastContext{ .value = .{ .value = field_val } };
1350 if (bit_offset_val_pl.data != 0) {
1351 try writer.writeAll("zig_shl_");
1352 try dg.renderTypeForBuiltinFnName(writer, ty);
1340 if (eff_num_fields == 0) {
13531341 try writer.writeByte('(');
1354 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
1355 try writer.writeAll(", ");
1356 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1342 try dg.renderValue(writer, ty, Value.undef, initializer_type);
13571343 try writer.writeByte(')');
1358 } else {
1359 try dg.renderIntCast(writer, ty, cast_context, field_ty, .FunctionArgument);
1360 }
1361
1362 if (needs_closing_paren) try writer.writeByte(')');
1363 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
1364
1365 bit_offset_val_pl.data += field_ty.bitSize(target);
1366 needs_closing_paren = true;
1367 eff_index += 1;
1368 }
1369 } else {
1370 try writer.writeByte('(');
1371 // a << a_off | b << b_off | c << c_off
1372 var empty = true;
1373 for (field_vals, 0..) |field_val, field_i| {
1374 if (ty.structFieldIsComptime(field_i)) continue;
1375 const field_ty = ty.structFieldType(field_i);
1376 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1377
1378 if (!empty) try writer.writeAll(" | ");
1379 try writer.writeByte('(');
1380 try dg.renderType(writer, ty);
1381 try writer.writeByte(')');
1344 } else if (ty.bitSize(mod) > 64) {
1345 // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off))
1346 var num_or = eff_num_fields - 1;
1347 while (num_or > 0) : (num_or -= 1) {
1348 try writer.writeAll("zig_or_");
1349 try dg.renderTypeForBuiltinFnName(writer, ty);
1350 try writer.writeByte('(');
1351 }
13821352
1383 if (bit_offset_val_pl.data != 0) {
1384 try dg.renderValue(writer, field_ty, field_val, .Other);
1385 try writer.writeAll(" << ");
1386 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1353 var eff_index: usize = 0;
1354 var needs_closing_paren = false;
1355 for (struct_obj.fields.values(), 0..) |field, field_i| {
1356 if (field.is_comptime) continue;
1357 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1358
1359 const field_val = switch (aggregate.storage) {
1360 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1361 .ty = field.ty.toIntern(),
1362 .storage = .{ .u64 = bytes[field_i] },
1363 } }),
1364 .elems => |elems| elems[field_i],
1365 .repeated_elem => |elem| elem,
1366 };
1367 const cast_context = IntCastContext{ .value = .{ .value = field_val.toValue() } };
1368 if (bit_offset != 0) {
1369 try writer.writeAll("zig_shl_");
1370 try dg.renderTypeForBuiltinFnName(writer, ty);
1371 try writer.writeByte('(');
1372 try dg.renderIntCast(writer, ty, cast_context, field.ty, .FunctionArgument);
1373 try writer.writeAll(", ");
1374 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1375 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1376 try writer.writeByte(')');
1377 } else {
1378 try dg.renderIntCast(writer, ty, cast_context, field.ty, .FunctionArgument);
1379 }
1380
1381 if (needs_closing_paren) try writer.writeByte(')');
1382 if (eff_index != eff_num_fields - 1) try writer.writeAll(", ");
1383
1384 bit_offset += field.ty.bitSize(mod);
1385 needs_closing_paren = true;
1386 eff_index += 1;
1387 }
13871388 } else {
1388 try dg.renderValue(writer, field_ty, field_val, .Other);
1389 try writer.writeByte('(');
1390 // a << a_off | b << b_off | c << c_off
1391 var empty = true;
1392 for (struct_obj.fields.values(), 0..) |field, field_i| {
1393 if (field.is_comptime) continue;
1394 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
1395
1396 if (!empty) try writer.writeAll(" | ");
1397 try writer.writeByte('(');
1398 try dg.renderType(writer, ty);
1399 try writer.writeByte(')');
1400
1401 const field_val = switch (aggregate.storage) {
1402 .bytes => |bytes| try mod.intern_pool.get(mod.gpa, .{ .int = .{
1403 .ty = field.ty.toIntern(),
1404 .storage = .{ .u64 = bytes[field_i] },
1405 } }),
1406 .elems => |elems| elems[field_i],
1407 .repeated_elem => |elem| elem,
1408 };
1409
1410 if (bit_offset != 0) {
1411 try dg.renderValue(writer, field.ty, field_val.toValue(), .Other);
1412 try writer.writeAll(" << ");
1413 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
1414 try dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
1415 } else {
1416 try dg.renderValue(writer, field.ty, field_val.toValue(), .Other);
1417 }
1418
1419 bit_offset += field.ty.bitSize(mod);
1420 empty = false;
1421 }
1422 try writer.writeByte(')');
13891423 }
1390
1391 bit_offset_val_pl.data += field_ty.bitSize(target);
1392 empty = false;
1393 }
1394 try writer.writeByte(')');
1424 },
13951425 }
13961426 },
1427 else => unreachable,
13971428 },
1398 .Union => {
1399 const union_obj = val.castTag(.@"union").?.data;
1400
1429 .un => |un| {
14011430 if (!location.isInitializer()) {
14021431 try writer.writeByte('(');
14031432 try dg.renderType(writer, ty);
14041433 try writer.writeByte(')');
14051434 }
14061435
1407 const field_i = ty.unionTagFieldIndex(union_obj.tag, dg.module).?;
1408 const field_ty = ty.unionFields().values()[field_i].ty;
1409 const field_name = ty.unionFields().keys()[field_i];
1410 if (ty.containerLayout() == .Packed) {
1411 if (field_ty.hasRuntimeBits()) {
1412 if (field_ty.isPtrAtRuntime()) {
1436 const field_i = ty.unionTagFieldIndex(un.tag.toValue(), mod).?;
1437 const field_ty = ty.unionFields(mod).values()[field_i].ty;
1438 const field_name = ty.unionFields(mod).keys()[field_i];
1439 if (ty.containerLayout(mod) == .Packed) {
1440 if (field_ty.hasRuntimeBits(mod)) {
1441 if (field_ty.isPtrAtRuntime(mod)) {
14131442 try writer.writeByte('(');
14141443 try dg.renderType(writer, ty);
14151444 try writer.writeByte(')');
1416 } else if (field_ty.zigTypeTag() == .Float) {
1445 } else if (field_ty.zigTypeTag(mod) == .Float) {
14171446 try writer.writeByte('(');
14181447 try dg.renderType(writer, ty);
14191448 try writer.writeByte(')');
14201449 }
1421 try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);
1450 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
14221451 } else {
14231452 try writer.writeAll("0");
14241453 }
......@@ -1426,44 +1455,28 @@ pub const DeclGen = struct {
14261455 }
14271456
14281457 try writer.writeByte('{');
1429 if (ty.unionTagTypeSafety()) |tag_ty| {
1430 const layout = ty.unionGetLayout(target);
1458 if (ty.unionTagTypeSafety(mod)) |tag_ty| {
1459 const layout = ty.unionGetLayout(mod);
14311460 if (layout.tag_size != 0) {
14321461 try writer.writeAll(" .tag = ");
1433 try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type);
1462 try dg.renderValue(writer, tag_ty, un.tag.toValue(), initializer_type);
14341463 }
1435 if (ty.unionHasAllZeroBitFieldTypes()) return try writer.writeByte('}');
1464 if (ty.unionHasAllZeroBitFieldTypes(mod)) return try writer.writeByte('}');
14361465 if (layout.tag_size != 0) try writer.writeByte(',');
14371466 try writer.writeAll(" .payload = {");
14381467 }
1439 if (field_ty.hasRuntimeBits()) {
1440 try writer.print(" .{ } = ", .{fmtIdent(field_name)});
1441 try dg.renderValue(writer, field_ty, union_obj.val, initializer_type);
1468 if (field_ty.hasRuntimeBits(mod)) {
1469 try writer.print(" .{ } = ", .{fmtIdent(mod.intern_pool.stringToSlice(field_name))});
1470 try dg.renderValue(writer, field_ty, un.val.toValue(), initializer_type);
14421471 try writer.writeByte(' ');
1443 } else for (ty.unionFields().values()) |field| {
1444 if (!field.ty.hasRuntimeBits()) continue;
1472 } else for (ty.unionFields(mod).values()) |field| {
1473 if (!field.ty.hasRuntimeBits(mod)) continue;
14451474 try dg.renderValue(writer, field.ty, Value.undef, initializer_type);
14461475 break;
14471476 }
1448 if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}');
1477 if (ty.unionTagTypeSafety(mod)) |_| try writer.writeByte('}');
14491478 try writer.writeByte('}');
14501479 },
1451
1452 .ComptimeInt => unreachable,
1453 .ComptimeFloat => unreachable,
1454 .Type => unreachable,
1455 .EnumLiteral => unreachable,
1456 .Void => unreachable,
1457 .NoReturn => unreachable,
1458 .Undefined => unreachable,
1459 .Null => unreachable,
1460 .Opaque => unreachable,
1461
1462 .Frame,
1463 .AnyFrame,
1464 => |tag| return dg.fail("TODO: C backend: implement value of type {s}", .{
1465 @tagName(tag),
1466 }),
14671480 }
14681481 }
14691482
......@@ -1478,12 +1491,12 @@ pub const DeclGen = struct {
14781491 },
14791492 ) !void {
14801493 const store = &dg.ctypes.set;
1481 const module = dg.module;
1494 const mod = dg.module;
14821495
1483 const fn_decl = module.declPtr(fn_decl_index);
1496 const fn_decl = mod.declPtr(fn_decl_index);
14841497 const fn_cty_idx = try dg.typeToIndex(fn_decl.ty, kind);
14851498
1486 const fn_info = fn_decl.ty.fnInfo();
1499 const fn_info = mod.typeToFunc(fn_decl.ty).?;
14871500 if (fn_info.cc == .Naked) {
14881501 switch (kind) {
14891502 .forward => try w.writeAll("zig_naked_decl "),
......@@ -1491,14 +1504,13 @@ pub const DeclGen = struct {
14911504 else => unreachable,
14921505 }
14931506 }
1494 if (fn_decl.val.castTag(.function)) |func_payload|
1495 if (func_payload.data.is_cold) try w.writeAll("zig_cold ");
1496 if (fn_info.return_type.tag() == .noreturn) try w.writeAll("zig_noreturn ");
1507 if (fn_decl.val.getFunction(mod)) |func| if (func.is_cold) try w.writeAll("zig_cold ");
1508 if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
14971509
14981510 const trailing = try renderTypePrefix(
14991511 dg.decl_index,
15001512 store.*,
1501 module,
1513 mod,
15021514 w,
15031515 fn_cty_idx,
15041516 .suffix,
......@@ -1512,8 +1524,8 @@ pub const DeclGen = struct {
15121524
15131525 switch (kind) {
15141526 .forward => {},
1515 .complete => if (fn_info.alignment > 0)
1516 try w.print(" zig_align_fn({})", .{fn_info.alignment}),
1527 .complete => if (fn_info.alignment.toByteUnitsOptional()) |a|
1528 try w.print(" zig_align_fn({})", .{a}),
15171529 else => unreachable,
15181530 }
15191531
......@@ -1525,7 +1537,7 @@ pub const DeclGen = struct {
15251537 try renderTypeSuffix(
15261538 dg.decl_index,
15271539 store.*,
1528 module,
1540 mod,
15291541 w,
15301542 fn_cty_idx,
15311543 .suffix,
......@@ -1537,8 +1549,8 @@ pub const DeclGen = struct {
15371549 );
15381550
15391551 switch (kind) {
1540 .forward => if (fn_info.alignment > 0)
1541 try w.print(" zig_align_fn({})", .{fn_info.alignment}),
1552 .forward => if (fn_info.alignment.toByteUnitsOptional()) |a|
1553 try w.print(" zig_align_fn({})", .{a}),
15421554 .complete => {},
15431555 else => unreachable,
15441556 }
......@@ -1577,9 +1589,9 @@ pub const DeclGen = struct {
15771589
15781590 fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
15791591 const store = &dg.ctypes.set;
1580 const module = dg.module;
1581 _ = try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, .{});
1582 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{});
1592 const mod = dg.module;
1593 _ = try renderTypePrefix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
1594 try renderTypeSuffix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
15831595 }
15841596
15851597 const IntCastContext = union(enum) {
......@@ -1619,18 +1631,18 @@ pub const DeclGen = struct {
16191631 /// | > 64 bit integer | < 64 bit integer | zig_make_<dest_ty>(0, src)
16201632 /// | > 64 bit integer | > 64 bit integer | zig_make_<dest_ty>(zig_hi_<src_ty>(src), zig_lo_<src_ty>(src))
16211633 fn renderIntCast(dg: *DeclGen, w: anytype, dest_ty: Type, context: IntCastContext, src_ty: Type, location: ValueRenderLocation) !void {
1622 const target = dg.module.getTarget();
1623 const dest_bits = dest_ty.bitSize(target);
1624 const dest_int_info = dest_ty.intInfo(target);
1634 const mod = dg.module;
1635 const dest_bits = dest_ty.bitSize(mod);
1636 const dest_int_info = dest_ty.intInfo(mod);
16251637
1626 const src_is_ptr = src_ty.isPtrAtRuntime();
1638 const src_is_ptr = src_ty.isPtrAtRuntime(mod);
16271639 const src_eff_ty: Type = if (src_is_ptr) switch (dest_int_info.signedness) {
16281640 .unsigned => Type.usize,
16291641 .signed => Type.isize,
16301642 } else src_ty;
16311643
1632 const src_bits = src_eff_ty.bitSize(target);
1633 const src_int_info = if (src_eff_ty.isAbiInt()) src_eff_ty.intInfo(target) else null;
1644 const src_bits = src_eff_ty.bitSize(mod);
1645 const src_int_info = if (src_eff_ty.isAbiInt(mod)) src_eff_ty.intInfo(mod) else null;
16341646 if (dest_bits <= 64 and src_bits <= 64) {
16351647 const needs_cast = src_int_info == null or
16361648 (toCIntBits(dest_int_info.bits) != toCIntBits(src_int_info.?.bits) or
......@@ -1703,8 +1715,8 @@ pub const DeclGen = struct {
17031715 alignment: u32,
17041716 kind: CType.Kind,
17051717 ) error{ OutOfMemory, AnalysisFail }!void {
1706 const target = dg.module.getTarget();
1707 const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target));
1718 const mod = dg.module;
1719 const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(mod));
17081720 try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas);
17091721 }
17101722
......@@ -1717,7 +1729,7 @@ pub const DeclGen = struct {
17171729 alignas: CType.AlignAs,
17181730 ) error{ OutOfMemory, AnalysisFail }!void {
17191731 const store = &dg.ctypes.set;
1720 const module = dg.module;
1732 const mod = dg.module;
17211733
17221734 switch (std.math.order(alignas.@"align", alignas.abi)) {
17231735 .lt => try w.print("zig_under_align({}) ", .{alignas.getAlign()}),
......@@ -1726,25 +1738,20 @@ pub const DeclGen = struct {
17261738 }
17271739
17281740 const trailing =
1729 try renderTypePrefix(dg.decl_index, store.*, module, w, cty_idx, .suffix, qualifiers);
1741 try renderTypePrefix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, qualifiers);
17301742 try w.print("{}", .{trailing});
17311743 try dg.writeCValue(w, name);
1732 try renderTypeSuffix(dg.decl_index, store.*, module, w, cty_idx, .suffix, .{});
1744 try renderTypeSuffix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, .{});
17331745 }
17341746
17351747 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
1736 switch (tv.val.tag()) {
1737 .extern_fn => return true,
1738 .function => {
1739 const func = tv.val.castTag(.function).?.data;
1740 return dg.module.decl_exports.contains(func.owner_decl);
1741 },
1742 .variable => {
1743 const variable = tv.val.castTag(.variable).?.data;
1744 return dg.module.decl_exports.contains(variable.owner_decl);
1745 },
1748 const mod = dg.module;
1749 return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) {
1750 .variable => |variable| mod.decl_exports.contains(variable.decl),
1751 .extern_func => true,
1752 .func => |func| mod.decl_exports.contains(mod.funcPtr(func.index).owner_decl),
17461753 else => unreachable,
1747 }
1754 };
17481755 }
17491756
17501757 fn writeCValue(dg: *DeclGen, w: anytype, c_value: CValue) !void {
......@@ -1819,7 +1826,7 @@ pub const DeclGen = struct {
18191826 try dg.writeCValue(writer, member);
18201827 }
18211828
1822 fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: *Module.Var) !void {
1829 fn renderFwdDecl(dg: *DeclGen, decl_index: Decl.Index, variable: InternPool.Key.Variable) !void {
18231830 const decl = dg.module.declPtr(decl_index);
18241831 const fwd_decl_writer = dg.fwd_decl.writer();
18251832 const is_global = dg.declIsGlobal(.{ .ty = decl.ty, .val = decl.val }) or variable.is_extern;
......@@ -1830,7 +1837,7 @@ pub const DeclGen = struct {
18301837 fwd_decl_writer,
18311838 decl.ty,
18321839 .{ .decl = decl_index },
1833 CQualifiers.init(.{ .@"const" = !variable.is_mutable }),
1840 CQualifiers.init(.{ .@"const" = variable.is_const }),
18341841 decl.@"align",
18351842 .complete,
18361843 );
......@@ -1838,19 +1845,20 @@ pub const DeclGen = struct {
18381845 }
18391846
18401847 fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
1841 const decl = dg.module.declPtr(decl_index);
1842 dg.module.markDeclAlive(decl);
1843
1844 if (dg.module.decl_exports.get(decl_index)) |exports| {
1845 try writer.writeAll(exports.items[export_index].options.name);
1846 } else if (decl.isExtern()) {
1847 try writer.writeAll(mem.span(decl.name));
1848 const mod = dg.module;
1849 const decl = mod.declPtr(decl_index);
1850 try mod.markDeclAlive(decl);
1851
1852 if (mod.decl_exports.get(decl_index)) |exports| {
1853 try writer.print("{}", .{exports.items[export_index].opts.name.fmt(&mod.intern_pool)});
1854 } else if (decl.isExtern(mod)) {
1855 try writer.print("{}", .{decl.name.fmt(&mod.intern_pool)});
18481856 } else {
18491857 // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
18501858 // expand to 3x the length of its input, but let's cut it off at a much shorter limit.
18511859 var name: [100]u8 = undefined;
18521860 var name_stream = std.io.fixedBufferStream(&name);
1853 decl.renderFullyQualifiedName(dg.module, name_stream.writer()) catch |err| switch (err) {
1861 decl.renderFullyQualifiedName(mod, name_stream.writer()) catch |err| switch (err) {
18541862 error.NoSpaceLeft => {},
18551863 };
18561864 try writer.print("{}__{d}", .{
......@@ -1894,18 +1902,18 @@ pub const DeclGen = struct {
18941902 .bits => {},
18951903 }
18961904
1897 const target = dg.module.getTarget();
1898 const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
1905 const mod = dg.module;
1906 const int_info = if (ty.isAbiInt(mod)) ty.intInfo(mod) else std.builtin.Type.Int{
18991907 .signedness = .unsigned,
1900 .bits = @intCast(u16, ty.bitSize(target)),
1908 .bits = @intCast(u16, ty.bitSize(mod)),
19011909 };
19021910
19031911 if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
19041912
1905 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
1913 const bits_ty = if (is_big) Type.u16 else Type.u8;
19061914 try writer.print(", {}", .{try dg.fmtIntLiteral(
1907 if (is_big) Type.u16 else Type.u8,
1908 Value.initPayload(&bits_pl.base),
1915 bits_ty,
1916 try mod.intValue(bits_ty, int_info.bits),
19091917 .FunctionArgument,
19101918 )});
19111919 }
......@@ -1916,6 +1924,7 @@ pub const DeclGen = struct {
19161924 val: Value,
19171925 loc: ValueRenderLocation,
19181926 ) !std.fmt.Formatter(formatIntLiteral) {
1927 const mod = dg.module;
19191928 const kind: CType.Kind = switch (loc) {
19201929 .FunctionArgument => .parameter,
19211930 .Initializer, .Other => .complete,
......@@ -1923,7 +1932,7 @@ pub const DeclGen = struct {
19231932 };
19241933 return std.fmt.Formatter(formatIntLiteral){ .data = .{
19251934 .dg = dg,
1926 .int_info = ty.intInfo(dg.module.getTarget()),
1935 .int_info = ty.intInfo(mod),
19271936 .kind = kind,
19281937 .cty = try dg.typeToCType(ty, kind),
19291938 .val = val,
......@@ -1979,7 +1988,7 @@ fn renderTypeName(
19791988 try w.print("{s} {s}{}__{d}", .{
19801989 @tagName(tag)["fwd_".len..],
19811990 attributes,
1982 fmtIdent(mem.span(mod.declPtr(owner_decl).name)),
1991 fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(owner_decl).name)),
19831992 @enumToInt(owner_decl),
19841993 });
19851994 },
......@@ -2392,15 +2401,20 @@ pub fn genGlobalAsm(mod: *Module, writer: anytype) !void {
23922401}
23932402
23942403pub fn genErrDecls(o: *Object) !void {
2404 const mod = o.dg.module;
23952405 const writer = o.writer();
23962406
23972407 try writer.writeAll("enum {\n");
23982408 o.indent_writer.pushIndent();
23992409 var max_name_len: usize = 0;
2400 for (o.dg.module.error_name_list.items, 0..) |name, value| {
2401 max_name_len = std.math.max(name.len, max_name_len);
2402 var err_pl = Value.Payload.Error{ .data = .{ .name = name } };
2403 try o.dg.renderValue(writer, Type.anyerror, Value.initPayload(&err_pl.base), .Other);
2410 for (mod.global_error_set.keys()[1..], 1..) |name_nts, value| {
2411 const name = mod.intern_pool.stringToSlice(name_nts);
2412 max_name_len = @max(name.len, max_name_len);
2413 const err_val = try mod.intern(.{ .err = .{
2414 .ty = .anyerror_type,
2415 .name = name_nts,
2416 } });
2417 try o.dg.renderValue(writer, Type.anyerror, err_val.toValue(), .Other);
24042418 try writer.print(" = {d}u,\n", .{value});
24052419 }
24062420 o.indent_writer.popIndent();
......@@ -2412,40 +2426,44 @@ pub fn genErrDecls(o: *Object) !void {
24122426 defer o.dg.gpa.free(name_buf);
24132427
24142428 @memcpy(name_buf[0..name_prefix.len], name_prefix);
2415 for (o.dg.module.error_name_list.items) |name| {
2429 for (mod.global_error_set.keys()) |name_nts| {
2430 const name = mod.intern_pool.stringToSlice(name_nts);
24162431 @memcpy(name_buf[name_prefix.len..][0..name.len], name);
24172432 const identifier = name_buf[0 .. name_prefix.len + name.len];
24182433
2419 var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len };
2420 const name_ty = Type.initPayload(&name_ty_pl.base);
2421
2422 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name };
2423 const name_val = Value.initPayload(&name_pl.base);
2434 const name_ty = try mod.arrayType(.{
2435 .len = name.len,
2436 .child = .u8_type,
2437 .sentinel = .zero_u8,
2438 });
2439 const name_val = try mod.intern(.{ .aggregate = .{
2440 .ty = name_ty.toIntern(),
2441 .storage = .{ .bytes = name },
2442 } });
24242443
24252444 try writer.writeAll("static ");
24262445 try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, Const, 0, .complete);
24272446 try writer.writeAll(" = ");
2428 try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer);
2447 try o.dg.renderValue(writer, name_ty, name_val.toValue(), .StaticInitializer);
24292448 try writer.writeAll(";\n");
24302449 }
24312450
2432 var name_array_ty_pl = Type.Payload.Array{ .base = .{ .tag = .array }, .data = .{
2433 .len = o.dg.module.error_name_list.items.len,
2434 .elem_type = Type.initTag(.const_slice_u8_sentinel_0),
2435 } };
2436 const name_array_ty = Type.initPayload(&name_array_ty_pl.base);
2451 const name_array_ty = try mod.arrayType(.{
2452 .len = mod.global_error_set.count(),
2453 .child = .slice_const_u8_sentinel_0_type,
2454 });
24372455
24382456 try writer.writeAll("static ");
24392457 try o.dg.renderTypeAndName(writer, name_array_ty, .{ .identifier = array_identifier }, Const, 0, .complete);
24402458 try writer.writeAll(" = {");
2441 for (o.dg.module.error_name_list.items, 0..) |name, value| {
2459 for (mod.global_error_set.keys(), 0..) |name_nts, value| {
2460 const name = mod.intern_pool.stringToSlice(name_nts);
24422461 if (value != 0) try writer.writeByte(',');
24432462
2444 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
2445 const len_val = Value.initPayload(&len_pl.base);
2463 const len_val = try mod.intValue(Type.usize, name.len);
24462464
24472465 try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
2448 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other),
2466 fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .StaticInitializer),
24492467 });
24502468 }
24512469 try writer.writeAll("};\n");
......@@ -2455,20 +2473,23 @@ fn genExports(o: *Object) !void {
24552473 const tracy = trace(@src());
24562474 defer tracy.end();
24572475
2476 const mod = o.dg.module;
2477 const ip = &mod.intern_pool;
24582478 const fwd_decl_writer = o.dg.fwd_decl.writer();
2459 if (o.dg.module.decl_exports.get(o.dg.decl_index.unwrap().?)) |exports| {
2479 if (mod.decl_exports.get(o.dg.decl_index.unwrap().?)) |exports| {
24602480 for (exports.items[1..], 1..) |@"export", i| {
24612481 try fwd_decl_writer.writeAll("zig_export(");
24622482 try o.dg.renderFunctionSignature(fwd_decl_writer, o.dg.decl_index.unwrap().?, .forward, .{ .export_index = @intCast(u32, i) });
24632483 try fwd_decl_writer.print(", {s}, {s});\n", .{
2464 fmtStringLiteral(exports.items[0].options.name, null),
2465 fmtStringLiteral(@"export".options.name, null),
2484 fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null),
2485 fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null),
24662486 });
24672487 }
24682488 }
24692489}
24702490
24712491pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
2492 const mod = o.dg.module;
24722493 const w = o.writer();
24732494 const key = lazy_fn.key_ptr.*;
24742495 const val = lazy_fn.value_ptr;
......@@ -2477,7 +2498,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
24772498 .tag_name => {
24782499 const enum_ty = val.data.tag_name;
24792500
2480 const name_slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
2501 const name_slice_ty = Type.slice_const_u8_sentinel_0;
24812502
24822503 try w.writeAll("static ");
24832504 try o.dg.renderType(w, name_slice_ty);
......@@ -2486,34 +2507,30 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
24862507 try w.writeByte('(');
24872508 try o.dg.renderTypeAndName(w, enum_ty, .{ .identifier = "tag" }, Const, 0, .complete);
24882509 try w.writeAll(") {\n switch (tag) {\n");
2489 for (enum_ty.enumFields().keys(), 0..) |name, index| {
2490 var tag_pl: Value.Payload.U32 = .{
2491 .base = .{ .tag = .enum_field_index },
2492 .data = @intCast(u32, index),
2493 };
2494 const tag_val = Value.initPayload(&tag_pl.base);
2510 for (enum_ty.enumFields(mod), 0..) |name_ip, index_usize| {
2511 const index = @intCast(u32, index_usize);
2512 const name = mod.intern_pool.stringToSlice(name_ip);
2513 const tag_val = try mod.enumValueFieldIndex(enum_ty, index);
24952514
2496 var int_pl: Value.Payload.U64 = undefined;
2497 const int_val = tag_val.enumToInt(enum_ty, &int_pl);
2515 const int_val = try tag_val.enumToInt(enum_ty, mod);
24982516
2499 var name_ty_pl = Type.Payload.Len{
2500 .base = .{ .tag = .array_u8_sentinel_0 },
2501 .data = name.len,
2502 };
2503 const name_ty = Type.initPayload(&name_ty_pl.base);
2504
2505 var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name };
2506 const name_val = Value.initPayload(&name_pl.base);
2507
2508 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len };
2509 const len_val = Value.initPayload(&len_pl.base);
2517 const name_ty = try mod.arrayType(.{
2518 .len = name.len,
2519 .child = .u8_type,
2520 .sentinel = .zero_u8,
2521 });
2522 const name_val = try mod.intern(.{ .aggregate = .{
2523 .ty = name_ty.toIntern(),
2524 .storage = .{ .bytes = name },
2525 } });
2526 const len_val = try mod.intValue(Type.usize, name.len);
25102527
25112528 try w.print(" case {}: {{\n static ", .{
25122529 try o.dg.fmtIntLiteral(enum_ty, int_val, .Other),
25132530 });
25142531 try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete);
25152532 try w.writeAll(" = ");
2516 try o.dg.renderValue(w, name_ty, name_val, .Initializer);
2533 try o.dg.renderValue(w, name_ty, name_val.toValue(), .Initializer);
25172534 try w.writeAll(";\n return (");
25182535 try o.dg.renderType(w, name_slice_ty);
25192536 try w.print("){{{}, {}}};\n", .{
......@@ -2529,7 +2546,7 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void {
25292546 try w.writeAll("}\n");
25302547 },
25312548 .never_tail, .never_inline => |fn_decl_index| {
2532 const fn_decl = o.dg.module.declPtr(fn_decl_index);
2549 const fn_decl = mod.declPtr(fn_decl_index);
25332550 const fn_cty = try o.dg.typeToCType(fn_decl.ty, .complete);
25342551 const fn_info = fn_cty.cast(CType.Payload.Function).?.data;
25352552
......@@ -2646,19 +2663,19 @@ pub fn genDecl(o: *Object) !void {
26462663 const tracy = trace(@src());
26472664 defer tracy.end();
26482665
2666 const mod = o.dg.module;
26492667 const decl = o.dg.decl.?;
26502668 const decl_c_value = .{ .decl = o.dg.decl_index.unwrap().? };
2651 const tv: TypedValue = .{ .ty = decl.ty, .val = decl.val };
2669 const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
26522670
2653 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime()) return;
2654 if (tv.val.tag() == .extern_fn) {
2671 if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return;
2672 if (tv.val.getExternFunc(mod)) |_| {
26552673 const fwd_decl_writer = o.dg.fwd_decl.writer();
26562674 try fwd_decl_writer.writeAll("zig_extern ");
26572675 try o.dg.renderFunctionSignature(fwd_decl_writer, decl_c_value.decl, .forward, .{ .export_index = 0 });
26582676 try fwd_decl_writer.writeAll(";\n");
26592677 try genExports(o);
2660 } else if (tv.val.castTag(.variable)) |var_payload| {
2661 const variable: *Module.Var = var_payload.data;
2678 } else if (tv.val.getVariable(mod)) |variable| {
26622679 try o.dg.renderFwdDecl(decl_c_value.decl, variable);
26632680 try genExports(o);
26642681
......@@ -2669,11 +2686,12 @@ pub fn genDecl(o: *Object) !void {
26692686 if (!is_global) try w.writeAll("static ");
26702687 if (variable.is_threadlocal) try w.writeAll("zig_threadlocal ");
26712688 if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage ");
2672 if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
2689 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
2690 try w.print("zig_linksection(\"{s}\", ", .{s});
26732691 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.@"align", .complete);
2674 if (decl.@"linksection" != null) try w.writeAll(", read, write)");
2692 if (decl.@"linksection" != .none) try w.writeAll(", read, write)");
26752693 try w.writeAll(" = ");
2676 try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer);
2694 try o.dg.renderValue(w, tv.ty, variable.init.toValue(), .StaticInitializer);
26772695 try w.writeByte(';');
26782696 try o.indent_writer.insertNewline();
26792697 } else {
......@@ -2686,9 +2704,10 @@ pub fn genDecl(o: *Object) !void {
26862704
26872705 const w = o.writer();
26882706 if (!is_global) try w.writeAll("static ");
2689 if (decl.@"linksection") |section| try w.print("zig_linksection(\"{s}\", ", .{section});
2707 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
2708 try w.print("zig_linksection(\"{s}\", ", .{s});
26902709 try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, decl.@"align", .complete);
2691 if (decl.@"linksection" != null) try w.writeAll(", read)");
2710 if (decl.@"linksection" != .none) try w.writeAll(", read)");
26922711 try w.writeAll(" = ");
26932712 try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer);
26942713 try w.writeAll(";\n");
......@@ -2704,8 +2723,9 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
27042723 .val = dg.decl.?.val,
27052724 };
27062725 const writer = dg.fwd_decl.writer();
2726 const mod = dg.module;
27072727
2708 switch (tv.ty.zigTypeTag()) {
2728 switch (tv.ty.zigTypeTag(mod)) {
27092729 .Fn => {
27102730 const is_global = dg.declIsGlobal(tv);
27112731 if (is_global) {
......@@ -2791,17 +2811,18 @@ fn genBodyResolveState(f: *Function, inst: Air.Inst.Index, leading_deaths: []con
27912811}
27922812
27932813fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutOfMemory }!void {
2814 const mod = f.object.dg.module;
2815 const ip = &mod.intern_pool;
27942816 const air_tags = f.air.instructions.items(.tag);
27952817
27962818 for (body) |inst| {
2797 if (f.liveness.isUnused(inst) and !f.air.mustLower(inst)) {
2819 if (f.liveness.isUnused(inst) and !f.air.mustLower(inst, ip))
27982820 continue;
2799 }
28002821
28012822 const result_value = switch (air_tags[inst]) {
28022823 // zig fmt: off
2803 .constant => unreachable, // excluded from function bodies
2804 .const_ty => unreachable, // excluded from function bodies
2824 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
2825
28052826 .arg => try airArg(f, inst),
28062827
28072828 .trap => try airTrap(f.object.writer()),
......@@ -2826,10 +2847,10 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
28262847 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
28272848 .rem => blk: {
28282849 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
2829 const lhs_scalar_ty = f.air.typeOf(bin_op.lhs).scalarType();
2850 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(mod);
28302851 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
28312852 // so we only check one.
2832 break :blk if (lhs_scalar_ty.isInt())
2853 break :blk if (lhs_scalar_ty.isInt(mod))
28332854 try airBinOp(f, inst, "%", "rem", .none)
28342855 else
28352856 try airBinFloatOp(f, inst, "fmod");
......@@ -3077,7 +3098,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
30773098fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: []const u8) !CValue {
30783099 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
30793100
3080 const inst_ty = f.air.typeOfIndex(inst);
3101 const inst_ty = f.typeOfIndex(inst);
30813102 const operand = try f.resolveInst(ty_op.operand);
30823103 try reap(f, inst, &.{ty_op.operand});
30833104
......@@ -3095,9 +3116,10 @@ fn airSliceField(f: *Function, inst: Air.Inst.Index, is_ptr: bool, field_name: [
30953116}
30963117
30973118fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3098 const inst_ty = f.air.typeOfIndex(inst);
3119 const mod = f.object.dg.module;
3120 const inst_ty = f.typeOfIndex(inst);
30993121 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3100 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {
3122 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
31013123 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
31023124 return .none;
31033125 }
......@@ -3120,13 +3142,14 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
31203142}
31213143
31223144fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3145 const mod = f.object.dg.module;
31233146 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
31243147 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
31253148
3126 const inst_ty = f.air.typeOfIndex(inst);
3127 const ptr_ty = f.air.typeOf(bin_op.lhs);
3128 const elem_ty = ptr_ty.childType();
3129 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime();
3149 const inst_ty = f.typeOfIndex(inst);
3150 const ptr_ty = f.typeOf(bin_op.lhs);
3151 const elem_ty = ptr_ty.childType(mod);
3152 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
31303153
31313154 const ptr = try f.resolveInst(bin_op.lhs);
31323155 const index = try f.resolveInst(bin_op.rhs);
......@@ -3141,7 +3164,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
31413164 try f.renderType(writer, inst_ty);
31423165 try writer.writeByte(')');
31433166 if (elem_has_bits) try writer.writeByte('&');
3144 if (elem_has_bits and ptr_ty.ptrSize() == .One) {
3167 if (elem_has_bits and ptr_ty.ptrSize(mod) == .One) {
31453168 // It's a pointer to an array, so we need to de-reference.
31463169 try f.writeCValueDeref(writer, ptr);
31473170 } else try f.writeCValue(writer, ptr, .Other);
......@@ -3155,9 +3178,10 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
31553178}
31563179
31573180fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3158 const inst_ty = f.air.typeOfIndex(inst);
3181 const mod = f.object.dg.module;
3182 const inst_ty = f.typeOfIndex(inst);
31593183 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3160 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {
3184 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
31613185 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
31623186 return .none;
31633187 }
......@@ -3180,13 +3204,14 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
31803204}
31813205
31823206fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3207 const mod = f.object.dg.module;
31833208 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
31843209 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
31853210
3186 const inst_ty = f.air.typeOfIndex(inst);
3187 const slice_ty = f.air.typeOf(bin_op.lhs);
3188 const elem_ty = slice_ty.elemType2();
3189 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime();
3211 const inst_ty = f.typeOfIndex(inst);
3212 const slice_ty = f.typeOf(bin_op.lhs);
3213 const elem_ty = slice_ty.elemType2(mod);
3214 const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(mod);
31903215
31913216 const slice = try f.resolveInst(bin_op.lhs);
31923217 const index = try f.resolveInst(bin_op.rhs);
......@@ -3209,9 +3234,10 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
32093234}
32103235
32113236fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
3237 const mod = f.object.dg.module;
32123238 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3213 const inst_ty = f.air.typeOfIndex(inst);
3214 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {
3239 const inst_ty = f.typeOfIndex(inst);
3240 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
32153241 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
32163242 return .none;
32173243 }
......@@ -3234,14 +3260,14 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue {
32343260}
32353261
32363262fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
3237 const inst_ty = f.air.typeOfIndex(inst);
3238 const elem_type = inst_ty.elemType();
3239 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty };
3263 const mod = f.object.dg.module;
3264 const inst_ty = f.typeOfIndex(inst);
3265 const elem_type = inst_ty.childType(mod);
3266 if (!elem_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty };
32403267
3241 const target = f.object.dg.module.getTarget();
32423268 const local = try f.allocLocalValue(
32433269 elem_type,
3244 inst_ty.ptrAlignment(target),
3270 inst_ty.ptrAlignment(mod),
32453271 );
32463272 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
32473273 const gpa = f.object.dg.module.gpa;
......@@ -3250,14 +3276,14 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
32503276}
32513277
32523278fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
3253 const inst_ty = f.air.typeOfIndex(inst);
3254 const elem_ty = inst_ty.elemType();
3255 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return .{ .undef = inst_ty };
3279 const mod = f.object.dg.module;
3280 const inst_ty = f.typeOfIndex(inst);
3281 const elem_ty = inst_ty.childType(mod);
3282 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return .{ .undef = inst_ty };
32563283
3257 const target = f.object.dg.module.getTarget();
32583284 const local = try f.allocLocalValue(
32593285 elem_ty,
3260 inst_ty.ptrAlignment(target),
3286 inst_ty.ptrAlignment(mod),
32613287 );
32623288 log.debug("%{d}: allocated unfreeable t{d}", .{ inst, local.new_local });
32633289 const gpa = f.object.dg.module.gpa;
......@@ -3266,7 +3292,7 @@ fn airRetPtr(f: *Function, inst: Air.Inst.Index) !CValue {
32663292}
32673293
32683294fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
3269 const inst_ty = f.air.typeOfIndex(inst);
3295 const inst_ty = f.typeOfIndex(inst);
32703296 const inst_cty = try f.typeToIndex(inst_ty, .parameter);
32713297
32723298 const i = f.next_arg_index;
......@@ -3290,14 +3316,15 @@ fn airArg(f: *Function, inst: Air.Inst.Index) !CValue {
32903316}
32913317
32923318fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
3319 const mod = f.object.dg.module;
32933320 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
32943321
3295 const ptr_ty = f.air.typeOf(ty_op.operand);
3296 const ptr_scalar_ty = ptr_ty.scalarType();
3297 const ptr_info = ptr_scalar_ty.ptrInfo().data;
3322 const ptr_ty = f.typeOf(ty_op.operand);
3323 const ptr_scalar_ty = ptr_ty.scalarType(mod);
3324 const ptr_info = ptr_scalar_ty.ptrInfo(mod);
32983325 const src_ty = ptr_info.pointee_type;
32993326
3300 if (!src_ty.hasRuntimeBitsIgnoreComptime()) {
3327 if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) {
33013328 try reap(f, inst, &.{ty_op.operand});
33023329 return .none;
33033330 }
......@@ -3306,9 +3333,8 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33063333
33073334 try reap(f, inst, &.{ty_op.operand});
33083335
3309 const target = f.object.dg.module.getTarget();
3310 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(target);
3311 const is_array = lowersToArray(src_ty, target);
3336 const is_aligned = ptr_info.@"align" == 0 or ptr_info.@"align" >= src_ty.abiAlignment(mod);
3337 const is_array = lowersToArray(src_ty, mod);
33123338 const need_memcpy = !is_aligned or is_array;
33133339
33143340 const writer = f.object.writer();
......@@ -3327,29 +3353,13 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33273353 try f.renderType(writer, src_ty);
33283354 try writer.writeAll("))");
33293355 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {
3330 var host_pl = Type.Payload.Bits{
3331 .base = .{ .tag = .int_unsigned },
3332 .data = ptr_info.host_size * 8,
3333 };
3334 const host_ty = Type.initPayload(&host_pl.base);
3356 const host_bits: u16 = ptr_info.host_size * 8;
3357 const host_ty = try mod.intType(.unsigned, host_bits);
33353358
3336 var bit_offset_ty_pl = Type.Payload.Bits{
3337 .base = .{ .tag = .int_unsigned },
3338 .data = Type.smallestUnsignedBits(host_pl.data - 1),
3339 };
3340 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
3359 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
3360 const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.bit_offset);
33413361
3342 var bit_offset_val_pl: Value.Payload.U64 = .{
3343 .base = .{ .tag = .int_u64 },
3344 .data = ptr_info.bit_offset,
3345 };
3346 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
3347
3348 var field_pl = Type.Payload.Bits{
3349 .base = .{ .tag = .int_unsigned },
3350 .data = @intCast(u16, src_ty.bitSize(target)),
3351 };
3352 const field_ty = Type.initPayload(&field_pl.base);
3362 const field_ty = try mod.intType(.unsigned, @intCast(u16, src_ty.bitSize(mod)));
33533363
33543364 try f.writeCValue(writer, local, .Other);
33553365 try v.elem(f, writer);
......@@ -3360,9 +3370,9 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33603370 try writer.writeAll("((");
33613371 try f.renderType(writer, field_ty);
33623372 try writer.writeByte(')');
3363 const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64;
3373 const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64;
33643374 if (cant_cast) {
3365 if (field_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
3375 if (field_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
33663376 try writer.writeAll("zig_lo_");
33673377 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
33683378 try writer.writeByte('(');
......@@ -3390,23 +3400,22 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue {
33903400}
33913401
33923402fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
3403 const mod = f.object.dg.module;
33933404 const un_op = f.air.instructions.items(.data)[inst].un_op;
33943405 const writer = f.object.writer();
3395 const target = f.object.dg.module.getTarget();
33963406 const op_inst = Air.refToIndex(un_op);
3397 const op_ty = f.air.typeOf(un_op);
3398 const ret_ty = if (is_ptr) op_ty.childType() else op_ty;
3399 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
3400 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
3407 const op_ty = f.typeOf(un_op);
3408 const ret_ty = if (is_ptr) op_ty.childType(mod) else op_ty;
3409 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
34013410
34023411 if (op_inst != null and f.air.instructions.items(.tag)[op_inst.?] == .call_always_tail) {
34033412 try reap(f, inst, &.{un_op});
34043413 _ = try airCall(f, op_inst.?, .always_tail);
3405 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {
3414 } else if (lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
34063415 const operand = try f.resolveInst(un_op);
34073416 try reap(f, inst, &.{un_op});
34083417 var deref = is_ptr;
3409 const is_array = lowersToArray(ret_ty, target);
3418 const is_array = lowersToArray(ret_ty, mod);
34103419 const ret_val = if (is_array) ret_val: {
34113420 const array_local = try f.allocLocal(inst, lowered_ret_ty);
34123421 try writer.writeAll("memcpy(");
......@@ -3435,22 +3444,23 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
34353444 } else {
34363445 try reap(f, inst, &.{un_op});
34373446 // Not even allowed to return void in a naked function.
3438 if (if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention() != .Naked else true)
3447 if (if (f.object.dg.decl) |decl| decl.ty.fnCallingConvention(mod) != .Naked else true)
34393448 try writer.writeAll("return;\n");
34403449 }
34413450 return .none;
34423451}
34433452
34443453fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
3454 const mod = f.object.dg.module;
34453455 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
34463456
34473457 const operand = try f.resolveInst(ty_op.operand);
34483458 try reap(f, inst, &.{ty_op.operand});
34493459
3450 const inst_ty = f.air.typeOfIndex(inst);
3451 const inst_scalar_ty = inst_ty.scalarType();
3452 const operand_ty = f.air.typeOf(ty_op.operand);
3453 const scalar_ty = operand_ty.scalarType();
3460 const inst_ty = f.typeOfIndex(inst);
3461 const inst_scalar_ty = inst_ty.scalarType(mod);
3462 const operand_ty = f.typeOf(ty_op.operand);
3463 const scalar_ty = operand_ty.scalarType(mod);
34543464
34553465 const writer = f.object.writer();
34563466 const local = try f.allocLocal(inst, inst_ty);
......@@ -3467,20 +3477,20 @@ fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue {
34673477}
34683478
34693479fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
3480 const mod = f.object.dg.module;
34703481 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
34713482
34723483 const operand = try f.resolveInst(ty_op.operand);
34733484 try reap(f, inst, &.{ty_op.operand});
3474 const inst_ty = f.air.typeOfIndex(inst);
3475 const inst_scalar_ty = inst_ty.scalarType();
3476 const target = f.object.dg.module.getTarget();
3477 const dest_int_info = inst_scalar_ty.intInfo(target);
3485 const inst_ty = f.typeOfIndex(inst);
3486 const inst_scalar_ty = inst_ty.scalarType(mod);
3487 const dest_int_info = inst_scalar_ty.intInfo(mod);
34783488 const dest_bits = dest_int_info.bits;
34793489 const dest_c_bits = toCIntBits(dest_int_info.bits) orelse
34803490 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3481 const operand_ty = f.air.typeOf(ty_op.operand);
3482 const scalar_ty = operand_ty.scalarType();
3483 const scalar_int_info = scalar_ty.intInfo(target);
3491 const operand_ty = f.typeOf(ty_op.operand);
3492 const scalar_ty = operand_ty.scalarType(mod);
3493 const scalar_int_info = scalar_ty.intInfo(mod);
34843494
34853495 const writer = f.object.writer();
34863496 const local = try f.allocLocal(inst, inst_ty);
......@@ -3508,14 +3518,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
35083518 try v.elem(f, writer);
35093519 } else switch (dest_int_info.signedness) {
35103520 .unsigned => {
3511 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
3512 defer arena.deinit();
3513
3514 const ExpectedContents = union { u: Value.Payload.U64, i: Value.Payload.I64 };
3515 var stack align(@alignOf(ExpectedContents)) =
3516 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
3517
3518 const mask_val = try inst_scalar_ty.maxInt(stack.get(), target);
3521 const mask_val = try inst_scalar_ty.maxIntScalar(mod, scalar_ty);
35193522 try writer.writeAll("zig_and_");
35203523 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
35213524 try writer.writeByte('(');
......@@ -3526,11 +3529,7 @@ fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue {
35263529 .signed => {
35273530 const c_bits = toCIntBits(scalar_int_info.bits) orelse
35283531 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
3529 var shift_pl = Value.Payload.U64{
3530 .base = .{ .tag = .int_u64 },
3531 .data = c_bits - dest_bits,
3532 };
3533 const shift_val = Value.initPayload(&shift_pl.base);
3532 const shift_val = try mod.intValue(Type.u8, c_bits - dest_bits);
35343533
35353534 try writer.writeAll("zig_shr_");
35363535 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
......@@ -3566,7 +3565,7 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
35663565 const operand = try f.resolveInst(un_op);
35673566 try reap(f, inst, &.{un_op});
35683567 const writer = f.object.writer();
3569 const inst_ty = f.air.typeOfIndex(inst);
3568 const inst_ty = f.typeOfIndex(inst);
35703569 const local = try f.allocLocal(inst, inst_ty);
35713570 const a = try Assignment.start(f, writer, inst_ty);
35723571 try f.writeCValue(writer, local, .Other);
......@@ -3577,17 +3576,18 @@ fn airBoolToInt(f: *Function, inst: Air.Inst.Index) !CValue {
35773576}
35783577
35793578fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
3579 const mod = f.object.dg.module;
35803580 // *a = b;
35813581 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
35823582
3583 const ptr_ty = f.air.typeOf(bin_op.lhs);
3584 const ptr_scalar_ty = ptr_ty.scalarType();
3585 const ptr_info = ptr_scalar_ty.ptrInfo().data;
3583 const ptr_ty = f.typeOf(bin_op.lhs);
3584 const ptr_scalar_ty = ptr_ty.scalarType(mod);
3585 const ptr_info = ptr_scalar_ty.ptrInfo(mod);
35863586
35873587 const ptr_val = try f.resolveInst(bin_op.lhs);
3588 const src_ty = f.air.typeOf(bin_op.rhs);
3588 const src_ty = f.typeOf(bin_op.rhs);
35893589
3590 const val_is_undef = if (f.air.value(bin_op.rhs)) |v| v.isUndefDeep() else false;
3590 const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep(mod) else false;
35913591
35923592 if (val_is_undef) {
35933593 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
......@@ -3602,10 +3602,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
36023602 return .none;
36033603 }
36043604
3605 const target = f.object.dg.module.getTarget();
36063605 const is_aligned = ptr_info.@"align" == 0 or
3607 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(target);
3608 const is_array = lowersToArray(ptr_info.pointee_type, target);
3606 ptr_info.@"align" >= ptr_info.pointee_type.abiAlignment(mod);
3607 const is_array = lowersToArray(ptr_info.pointee_type, mod);
36093608 const need_memcpy = !is_aligned or is_array;
36103609
36113610 const src_val = try f.resolveInst(bin_op.rhs);
......@@ -3647,22 +3646,12 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
36473646 }
36483647 } else if (ptr_info.host_size > 0 and ptr_info.vector_index == .none) {
36493648 const host_bits = ptr_info.host_size * 8;
3650 var host_pl = Type.Payload.Bits{ .base = .{ .tag = .int_unsigned }, .data = host_bits };
3651 const host_ty = Type.initPayload(&host_pl.base);
3649 const host_ty = try mod.intType(.unsigned, host_bits);
36523650
3653 var bit_offset_ty_pl = Type.Payload.Bits{
3654 .base = .{ .tag = .int_unsigned },
3655 .data = Type.smallestUnsignedBits(host_bits - 1),
3656 };
3657 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
3658
3659 var bit_offset_val_pl: Value.Payload.U64 = .{
3660 .base = .{ .tag = .int_u64 },
3661 .data = ptr_info.bit_offset,
3662 };
3663 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
3651 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(host_bits - 1));
3652 const bit_offset_val = try mod.intValue(bit_offset_ty, ptr_info.bit_offset);
36643653
3665 const src_bits = src_ty.bitSize(target);
3654 const src_bits = src_ty.bitSize(mod);
36663655
36673656 const ExpectedContents = [BigInt.Managed.default_capacity]BigIntLimb;
36683657 var stack align(@alignOf(ExpectedContents)) =
......@@ -3675,11 +3664,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
36753664 try mask.shiftLeft(&mask, ptr_info.bit_offset);
36763665 try mask.bitNotWrap(&mask, .unsigned, host_bits);
36773666
3678 var mask_pl = Value.Payload.BigInt{
3679 .base = .{ .tag = .int_big_positive },
3680 .data = mask.limbs[0..mask.len()],
3681 };
3682 const mask_val = Value.initPayload(&mask_pl.base);
3667 const mask_val = try mod.intValue_big(host_ty, mask.toConst());
36833668
36843669 try f.writeCValueDeref(writer, ptr_val);
36853670 try v.elem(f, writer);
......@@ -3693,9 +3678,9 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
36933678 try writer.print(", {x}), zig_shl_", .{try f.fmtIntLiteral(host_ty, mask_val)});
36943679 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
36953680 try writer.writeByte('(');
3696 const cant_cast = host_ty.isInt() and host_ty.bitSize(target) > 64;
3681 const cant_cast = host_ty.isInt(mod) and host_ty.bitSize(mod) > 64;
36973682 if (cant_cast) {
3698 if (src_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
3683 if (src_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
36993684 try writer.writeAll("zig_make_");
37003685 try f.object.dg.renderTypeForBuiltinFnName(writer, host_ty);
37013686 try writer.writeAll("(0, ");
......@@ -3705,7 +3690,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
37053690 try writer.writeByte(')');
37063691 }
37073692
3708 if (src_ty.isPtrAtRuntime()) {
3693 if (src_ty.isPtrAtRuntime(mod)) {
37093694 try writer.writeByte('(');
37103695 try f.renderType(writer, Type.usize);
37113696 try writer.writeByte(')');
......@@ -3728,6 +3713,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
37283713}
37293714
37303715fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue {
3716 const mod = f.object.dg.module;
37313717 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
37323718 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
37333719
......@@ -3735,9 +3721,9 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
37353721 const rhs = try f.resolveInst(bin_op.rhs);
37363722 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
37373723
3738 const inst_ty = f.air.typeOfIndex(inst);
3739 const operand_ty = f.air.typeOf(bin_op.lhs);
3740 const scalar_ty = operand_ty.scalarType();
3724 const inst_ty = f.typeOfIndex(inst);
3725 const operand_ty = f.typeOf(bin_op.lhs);
3726 const scalar_ty = operand_ty.scalarType(mod);
37413727
37423728 const w = f.object.writer();
37433729 const local = try f.allocLocal(inst, inst_ty);
......@@ -3765,15 +3751,16 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
37653751}
37663752
37673753fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
3754 const mod = f.object.dg.module;
37683755 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
3769 const operand_ty = f.air.typeOf(ty_op.operand);
3770 const scalar_ty = operand_ty.scalarType();
3771 if (scalar_ty.tag() != .bool) return try airUnBuiltinCall(f, inst, "not", .bits);
3756 const operand_ty = f.typeOf(ty_op.operand);
3757 const scalar_ty = operand_ty.scalarType(mod);
3758 if (scalar_ty.ip_index != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);
37723759
37733760 const op = try f.resolveInst(ty_op.operand);
37743761 try reap(f, inst, &.{ty_op.operand});
37753762
3776 const inst_ty = f.air.typeOfIndex(inst);
3763 const inst_ty = f.typeOfIndex(inst);
37773764
37783765 const writer = f.object.writer();
37793766 const local = try f.allocLocal(inst, inst_ty);
......@@ -3797,18 +3784,18 @@ fn airBinOp(
37973784 operation: []const u8,
37983785 info: BuiltinInfo,
37993786) !CValue {
3787 const mod = f.object.dg.module;
38003788 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
3801 const operand_ty = f.air.typeOf(bin_op.lhs);
3802 const scalar_ty = operand_ty.scalarType();
3803 const target = f.object.dg.module.getTarget();
3804 if ((scalar_ty.isInt() and scalar_ty.bitSize(target) > 64) or scalar_ty.isRuntimeFloat())
3789 const operand_ty = f.typeOf(bin_op.lhs);
3790 const scalar_ty = operand_ty.scalarType(mod);
3791 if ((scalar_ty.isInt(mod) and scalar_ty.bitSize(mod) > 64) or scalar_ty.isRuntimeFloat())
38053792 return try airBinBuiltinCall(f, inst, operation, info);
38063793
38073794 const lhs = try f.resolveInst(bin_op.lhs);
38083795 const rhs = try f.resolveInst(bin_op.rhs);
38093796 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
38103797
3811 const inst_ty = f.air.typeOfIndex(inst);
3798 const inst_ty = f.typeOfIndex(inst);
38123799
38133800 const writer = f.object.writer();
38143801 const local = try f.allocLocal(inst, inst_ty);
......@@ -3835,12 +3822,12 @@ fn airCmpOp(
38353822 data: anytype,
38363823 operator: std.math.CompareOperator,
38373824) !CValue {
3838 const lhs_ty = f.air.typeOf(data.lhs);
3839 const scalar_ty = lhs_ty.scalarType();
3825 const mod = f.object.dg.module;
3826 const lhs_ty = f.typeOf(data.lhs);
3827 const scalar_ty = lhs_ty.scalarType(mod);
38403828
3841 const target = f.object.dg.module.getTarget();
3842 const scalar_bits = scalar_ty.bitSize(target);
3843 if (scalar_ty.isInt() and scalar_bits > 64)
3829 const scalar_bits = scalar_ty.bitSize(mod);
3830 if (scalar_ty.isInt(mod) and scalar_bits > 64)
38443831 return airCmpBuiltinCall(
38453832 f,
38463833 inst,
......@@ -3852,13 +3839,13 @@ fn airCmpOp(
38523839 if (scalar_ty.isRuntimeFloat())
38533840 return airCmpBuiltinCall(f, inst, data, operator, .operator, .none);
38543841
3855 const inst_ty = f.air.typeOfIndex(inst);
3842 const inst_ty = f.typeOfIndex(inst);
38563843 const lhs = try f.resolveInst(data.lhs);
38573844 const rhs = try f.resolveInst(data.rhs);
38583845 try reap(f, inst, &.{ data.lhs, data.rhs });
38593846
3860 const rhs_ty = f.air.typeOf(data.rhs);
3861 const need_cast = lhs_ty.isSinglePointer() or rhs_ty.isSinglePointer();
3847 const rhs_ty = f.typeOf(data.rhs);
3848 const need_cast = lhs_ty.isSinglePointer(mod) or rhs_ty.isSinglePointer(mod);
38623849 const writer = f.object.writer();
38633850 const local = try f.allocLocal(inst, inst_ty);
38643851 const v = try Vectorize.start(f, inst, writer, lhs_ty);
......@@ -3885,12 +3872,12 @@ fn airEquality(
38853872 inst: Air.Inst.Index,
38863873 operator: std.math.CompareOperator,
38873874) !CValue {
3875 const mod = f.object.dg.module;
38883876 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
38893877
3890 const operand_ty = f.air.typeOf(bin_op.lhs);
3891 const target = f.object.dg.module.getTarget();
3892 const operand_bits = operand_ty.bitSize(target);
3893 if (operand_ty.isInt() and operand_bits > 64)
3878 const operand_ty = f.typeOf(bin_op.lhs);
3879 const operand_bits = operand_ty.bitSize(mod);
3880 if (operand_ty.isInt(mod) and operand_bits > 64)
38943881 return airCmpBuiltinCall(
38953882 f,
38963883 inst,
......@@ -3907,12 +3894,12 @@ fn airEquality(
39073894 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
39083895
39093896 const writer = f.object.writer();
3910 const inst_ty = f.air.typeOfIndex(inst);
3897 const inst_ty = f.typeOfIndex(inst);
39113898 const local = try f.allocLocal(inst, inst_ty);
39123899 try f.writeCValue(writer, local, .Other);
39133900 try writer.writeAll(" = ");
39143901
3915 if (operand_ty.zigTypeTag() == .Optional and !operand_ty.optionalReprIsPayload()) {
3902 if (operand_ty.zigTypeTag(mod) == .Optional and !operand_ty.optionalReprIsPayload(mod)) {
39163903 // (A && B) || (C && (A == B))
39173904 // A = lhs.is_null ; B = rhs.is_null ; C = rhs.payload == lhs.payload
39183905
......@@ -3951,7 +3938,7 @@ fn airEquality(
39513938fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
39523939 const un_op = f.air.instructions.items(.data)[inst].un_op;
39533940
3954 const inst_ty = f.air.typeOfIndex(inst);
3941 const inst_ty = f.typeOfIndex(inst);
39553942 const operand = try f.resolveInst(un_op);
39563943 try reap(f, inst, &.{un_op});
39573944
......@@ -3965,6 +3952,7 @@ fn airCmpLtErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue {
39653952}
39663953
39673954fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
3955 const mod = f.object.dg.module;
39683956 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
39693957 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
39703958
......@@ -3972,9 +3960,9 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
39723960 const rhs = try f.resolveInst(bin_op.rhs);
39733961 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
39743962
3975 const inst_ty = f.air.typeOfIndex(inst);
3976 const inst_scalar_ty = inst_ty.scalarType();
3977 const elem_ty = inst_scalar_ty.elemType2();
3963 const inst_ty = f.typeOfIndex(inst);
3964 const inst_scalar_ty = inst_ty.scalarType(mod);
3965 const elem_ty = inst_scalar_ty.elemType2(mod);
39783966
39793967 const local = try f.allocLocal(inst, inst_ty);
39803968 const writer = f.object.writer();
......@@ -3983,7 +3971,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
39833971 try v.elem(f, writer);
39843972 try writer.writeAll(" = ");
39853973
3986 if (elem_ty.hasRuntimeBitsIgnoreComptime()) {
3974 if (elem_ty.hasRuntimeBitsIgnoreComptime(mod)) {
39873975 // We must convert to and from integer types to prevent UB if the operation
39883976 // results in a NULL pointer, or if LHS is NULL. The operation is only UB
39893977 // if the result is NULL and then dereferenced.
......@@ -4012,13 +4000,13 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
40124000}
40134001
40144002fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []const u8) !CValue {
4003 const mod = f.object.dg.module;
40154004 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
40164005
4017 const inst_ty = f.air.typeOfIndex(inst);
4018 const inst_scalar_ty = inst_ty.scalarType();
4006 const inst_ty = f.typeOfIndex(inst);
4007 const inst_scalar_ty = inst_ty.scalarType(mod);
40194008
4020 const target = f.object.dg.module.getTarget();
4021 if (inst_scalar_ty.isInt() and inst_scalar_ty.bitSize(target) > 64)
4009 if (inst_scalar_ty.isInt(mod) and inst_scalar_ty.bitSize(mod) > 64)
40224010 return try airBinBuiltinCall(f, inst, operation[1..], .none);
40234011 if (inst_scalar_ty.isRuntimeFloat())
40244012 return try airBinFloatOp(f, inst, operation);
......@@ -4054,6 +4042,7 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
40544042}
40554043
40564044fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
4045 const mod = f.object.dg.module;
40574046 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
40584047 const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data;
40594048
......@@ -4061,9 +4050,8 @@ fn airSlice(f: *Function, inst: Air.Inst.Index) !CValue {
40614050 const len = try f.resolveInst(bin_op.rhs);
40624051 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
40634052
4064 const inst_ty = f.air.typeOfIndex(inst);
4065 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4066 const ptr_ty = inst_ty.slicePtrFieldType(&buf);
4053 const inst_ty = f.typeOfIndex(inst);
4054 const ptr_ty = inst_ty.slicePtrFieldType(mod);
40674055
40684056 const writer = f.object.writer();
40694057 const local = try f.allocLocal(inst, inst_ty);
......@@ -4092,12 +4080,11 @@ fn airCall(
40924080 inst: Air.Inst.Index,
40934081 modifier: std.builtin.CallModifier,
40944082) !CValue {
4083 const mod = f.object.dg.module;
40954084 // Not even allowed to call panic in a naked function.
4096 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none;
4085 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
40974086
40984087 const gpa = f.object.dg.gpa;
4099 const module = f.object.dg.module;
4100 const target = module.getTarget();
41014088 const writer = f.object.writer();
41024089
41034090 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
......@@ -4107,7 +4094,7 @@ fn airCall(
41074094 const resolved_args = try gpa.alloc(CValue, args.len);
41084095 defer gpa.free(resolved_args);
41094096 for (resolved_args, args) |*resolved_arg, arg| {
4110 const arg_ty = f.air.typeOf(arg);
4097 const arg_ty = f.typeOf(arg);
41114098 const arg_cty = try f.typeToIndex(arg_ty, .parameter);
41124099 if (f.indexToCType(arg_cty).tag() == .void) {
41134100 resolved_arg.* = .none;
......@@ -4115,8 +4102,7 @@ fn airCall(
41154102 }
41164103 resolved_arg.* = try f.resolveInst(arg);
41174104 if (arg_cty != try f.typeToIndex(arg_ty, .complete)) {
4118 var lowered_arg_buf: LowerFnRetTyBuffer = undefined;
4119 const lowered_arg_ty = lowerFnRetTy(arg_ty, &lowered_arg_buf, target);
4105 const lowered_arg_ty = try lowerFnRetTy(arg_ty, mod);
41204106
41214107 const array_local = try f.allocLocal(inst, lowered_arg_ty);
41224108 try writer.writeAll("memcpy(");
......@@ -4138,22 +4124,21 @@ fn airCall(
41384124 for (args) |arg| try bt.feed(arg);
41394125 }
41404126
4141 const callee_ty = f.air.typeOf(pl_op.operand);
4142 const fn_ty = switch (callee_ty.zigTypeTag()) {
4127 const callee_ty = f.typeOf(pl_op.operand);
4128 const fn_ty = switch (callee_ty.zigTypeTag(mod)) {
41434129 .Fn => callee_ty,
4144 .Pointer => callee_ty.childType(),
4130 .Pointer => callee_ty.childType(mod),
41454131 else => unreachable,
41464132 };
41474133
4148 const ret_ty = fn_ty.fnReturnType();
4149 var lowered_ret_buf: LowerFnRetTyBuffer = undefined;
4150 const lowered_ret_ty = lowerFnRetTy(ret_ty, &lowered_ret_buf, target);
4134 const ret_ty = fn_ty.fnReturnType(mod);
4135 const lowered_ret_ty = try lowerFnRetTy(ret_ty, mod);
41514136
41524137 const result_local = result: {
41534138 if (modifier == .always_tail) {
41544139 try writer.writeAll("zig_always_tail return ");
41554140 break :result .none;
4156 } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime()) {
4141 } else if (!lowered_ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
41574142 break :result .none;
41584143 } else if (f.liveness.isUnused(inst)) {
41594144 try writer.writeByte('(');
......@@ -4171,19 +4156,22 @@ fn airCall(
41714156 callee: {
41724157 known: {
41734158 const fn_decl = fn_decl: {
4174 const callee_val = f.air.value(pl_op.operand) orelse break :known;
4175 break :fn_decl switch (callee_val.tag()) {
4176 .extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,
4177 .function => callee_val.castTag(.function).?.data.owner_decl,
4178 .decl_ref => callee_val.castTag(.decl_ref).?.data,
4159 const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
4160 break :fn_decl switch (mod.intern_pool.indexToKey(callee_val.ip_index)) {
4161 .extern_func => |extern_func| extern_func.decl,
4162 .func => |func| mod.funcPtr(func.index).owner_decl,
4163 .ptr => |ptr| switch (ptr.addr) {
4164 .decl => |decl| decl,
4165 else => break :known,
4166 },
41794167 else => break :known,
41804168 };
41814169 };
41824170 switch (modifier) {
41834171 .auto, .always_tail => try f.object.dg.renderDeclName(writer, fn_decl, 0),
4184 inline .never_tail, .never_inline => |mod| try writer.writeAll(try f.getLazyFnName(
4185 @unionInit(LazyFnKey, @tagName(mod), fn_decl),
4186 @unionInit(LazyFnValue.Data, @tagName(mod), {}),
4172 inline .never_tail, .never_inline => |m| try writer.writeAll(try f.getLazyFnName(
4173 @unionInit(LazyFnKey, @tagName(m), fn_decl),
4174 @unionInit(LazyFnValue.Data, @tagName(m), {}),
41874175 )),
41884176 else => unreachable,
41894177 }
......@@ -4211,7 +4199,7 @@ fn airCall(
42114199 try writer.writeAll(");\n");
42124200
42134201 const result = result: {
4214 if (result_local == .none or !lowersToArray(ret_ty, target))
4202 if (result_local == .none or !lowersToArray(ret_ty, mod))
42154203 break :result result_local;
42164204
42174205 const array_local = try f.allocLocal(inst, ret_ty);
......@@ -4245,18 +4233,21 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
42454233}
42464234
42474235fn airDbgInline(f: *Function, inst: Air.Inst.Index) !CValue {
4248 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
4249 const writer = f.object.writer();
4250 const function = f.air.values[ty_pl.payload].castTag(.function).?.data;
4236 const ty_fn = f.air.instructions.items(.data)[inst].ty_fn;
42514237 const mod = f.object.dg.module;
4252 try writer.print("/* dbg func:{s} */\n", .{mod.declPtr(function.owner_decl).name});
4238 const writer = f.object.writer();
4239 const function = mod.funcPtr(ty_fn.func);
4240 try writer.print("/* dbg func:{s} */\n", .{
4241 mod.intern_pool.stringToSlice(mod.declPtr(function.owner_decl).name),
4242 });
42534243 return .none;
42544244}
42554245
42564246fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
4247 const mod = f.object.dg.module;
42574248 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
42584249 const name = f.air.nullTerminatedString(pl_op.payload);
4259 const operand_is_undef = if (f.air.value(pl_op.operand)) |v| v.isUndefDeep() else false;
4250 const operand_is_undef = if (try f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep(mod) else false;
42604251 if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
42614252
42624253 try reap(f, inst, &.{pl_op.operand});
......@@ -4266,6 +4257,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
42664257}
42674258
42684259fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
4260 const mod = f.object.dg.module;
42694261 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
42704262 const extra = f.air.extraData(Air.Block, ty_pl.payload);
42714263 const body = f.air.extra[extra.end..][0..extra.data.body_len];
......@@ -4275,8 +4267,8 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
42754267 f.next_block_index += 1;
42764268 const writer = f.object.writer();
42774269
4278 const inst_ty = f.air.typeOfIndex(inst);
4279 const result = if (inst_ty.tag() != .void and !f.liveness.isUnused(inst))
4270 const inst_ty = f.typeOfIndex(inst);
4271 const result = if (inst_ty.ip_index != .void_type and !f.liveness.isUnused(inst))
42804272 try f.allocLocal(inst, inst_ty)
42814273 else
42824274 .none;
......@@ -4298,7 +4290,7 @@ fn airBlock(f: *Function, inst: Air.Inst.Index) !CValue {
42984290 try f.object.indent_writer.insertNewline();
42994291
43004292 // noreturn blocks have no `br` instructions reaching them, so we don't want a label
4301 if (!f.air.typeOfIndex(inst).isNoReturn()) {
4293 if (!f.typeOfIndex(inst).isNoReturn(mod)) {
43024294 // label must be followed by an expression, include an empty one.
43034295 try writer.print("zig_block_{d}:;\n", .{block_id});
43044296 }
......@@ -4310,15 +4302,16 @@ fn airTry(f: *Function, inst: Air.Inst.Index) !CValue {
43104302 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
43114303 const extra = f.air.extraData(Air.Try, pl_op.payload);
43124304 const body = f.air.extra[extra.end..][0..extra.data.body_len];
4313 const err_union_ty = f.air.typeOf(pl_op.operand);
4305 const err_union_ty = f.typeOf(pl_op.operand);
43144306 return lowerTry(f, inst, pl_op.operand, body, err_union_ty, false);
43154307}
43164308
43174309fn airTryPtr(f: *Function, inst: Air.Inst.Index) !CValue {
4310 const mod = f.object.dg.module;
43184311 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
43194312 const extra = f.air.extraData(Air.TryPtr, ty_pl.payload);
43204313 const body = f.air.extra[extra.end..][0..extra.data.body_len];
4321 const err_union_ty = f.air.typeOf(extra.data.ptr).childType();
4314 const err_union_ty = f.typeOf(extra.data.ptr).childType(mod);
43224315 return lowerTry(f, inst, extra.data.ptr, body, err_union_ty, true);
43234316}
43244317
......@@ -4330,14 +4323,15 @@ fn lowerTry(
43304323 err_union_ty: Type,
43314324 is_ptr: bool,
43324325) !CValue {
4326 const mod = f.object.dg.module;
43334327 const err_union = try f.resolveInst(operand);
4334 const inst_ty = f.air.typeOfIndex(inst);
4328 const inst_ty = f.typeOfIndex(inst);
43354329 const liveness_condbr = f.liveness.getCondBr(inst);
43364330 const writer = f.object.writer();
4337 const payload_ty = err_union_ty.errorUnionPayload();
4338 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
4331 const payload_ty = err_union_ty.errorUnionPayload(mod);
4332 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
43394333
4340 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
4334 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
43414335 try writer.writeAll("if (");
43424336 if (!payload_has_bits) {
43434337 if (is_ptr)
......@@ -4399,7 +4393,7 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
43994393
44004394 // If result is .none then the value of the block is unused.
44014395 if (result != .none) {
4402 const operand_ty = f.air.typeOf(branch.operand);
4396 const operand_ty = f.typeOf(branch.operand);
44034397 const operand = try f.resolveInst(branch.operand);
44044398 try reap(f, inst, &.{branch.operand});
44054399
......@@ -4416,10 +4410,10 @@ fn airBr(f: *Function, inst: Air.Inst.Index) !CValue {
44164410
44174411fn airBitcast(f: *Function, inst: Air.Inst.Index) !CValue {
44184412 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
4419 const dest_ty = f.air.typeOfIndex(inst);
4413 const dest_ty = f.typeOfIndex(inst);
44204414
44214415 const operand = try f.resolveInst(ty_op.operand);
4422 const operand_ty = f.air.typeOf(ty_op.operand);
4416 const operand_ty = f.typeOf(ty_op.operand);
44234417
44244418 const bitcasted = try bitcast(f, dest_ty, operand, operand_ty);
44254419 try reap(f, inst, &.{ty_op.operand});
......@@ -4431,6 +4425,8 @@ const LocalResult = struct {
44314425 need_free: bool,
44324426
44334427 fn move(lr: LocalResult, f: *Function, inst: Air.Inst.Index, dest_ty: Type) !CValue {
4428 const mod = f.object.dg.module;
4429
44344430 if (lr.need_free) {
44354431 // Move the freshly allocated local to be owned by this instruction,
44364432 // by returning it here instead of freeing it.
......@@ -4441,7 +4437,7 @@ const LocalResult = struct {
44414437 try lr.free(f);
44424438 const writer = f.object.writer();
44434439 try f.writeCValue(writer, local, .Other);
4444 if (dest_ty.isAbiInt()) {
4440 if (dest_ty.isAbiInt(mod)) {
44454441 try writer.writeAll(" = ");
44464442 } else {
44474443 try writer.writeAll(" = (");
......@@ -4461,12 +4457,13 @@ const LocalResult = struct {
44614457};
44624458
44634459fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !LocalResult {
4464 const target = f.object.dg.module.getTarget();
4460 const mod = f.object.dg.module;
4461 const target = mod.getTarget();
44654462 const writer = f.object.writer();
44664463
4467 if (operand_ty.isAbiInt() and dest_ty.isAbiInt()) {
4468 const src_info = dest_ty.intInfo(target);
4469 const dest_info = operand_ty.intInfo(target);
4464 if (operand_ty.isAbiInt(mod) and dest_ty.isAbiInt(mod)) {
4465 const src_info = dest_ty.intInfo(mod);
4466 const dest_info = operand_ty.intInfo(mod);
44704467 if (src_info.signedness == dest_info.signedness and
44714468 src_info.bits == dest_info.bits)
44724469 {
......@@ -4477,7 +4474,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
44774474 }
44784475 }
44794476
4480 if (dest_ty.isPtrAtRuntime() and operand_ty.isPtrAtRuntime()) {
4477 if (dest_ty.isPtrAtRuntime(mod) and operand_ty.isPtrAtRuntime(mod)) {
44814478 const local = try f.allocLocal(0, dest_ty);
44824479 try f.writeCValue(writer, local, .Other);
44834480 try writer.writeAll(" = (");
......@@ -4494,7 +4491,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
44944491 const operand_lval = if (operand == .constant) blk: {
44954492 const operand_local = try f.allocLocal(0, operand_ty);
44964493 try f.writeCValue(writer, operand_local, .Other);
4497 if (operand_ty.isAbiInt()) {
4494 if (operand_ty.isAbiInt(mod)) {
44984495 try writer.writeAll(" = ");
44994496 } else {
45004497 try writer.writeAll(" = (");
......@@ -4516,13 +4513,10 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
45164513 try writer.writeAll("));\n");
45174514
45184515 // Ensure padding bits have the expected value.
4519 if (dest_ty.isAbiInt()) {
4516 if (dest_ty.isAbiInt(mod)) {
45204517 const dest_cty = try f.typeToCType(dest_ty, .complete);
4521 const dest_info = dest_ty.intInfo(target);
4522 var info_ty_pl = Type.Payload.Bits{ .base = .{ .tag = switch (dest_info.signedness) {
4523 .unsigned => .int_unsigned,
4524 .signed => .int_signed,
4525 } }, .data = dest_info.bits };
4518 const dest_info = dest_ty.intInfo(mod);
4519 var bits: u16 = dest_info.bits;
45264520 var wrap_cty: ?CType = null;
45274521 var need_bitcasts = false;
45284522
......@@ -4535,9 +4529,9 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
45354529 const elem_cty = f.indexToCType(pl.data.elem_type);
45364530 wrap_cty = elem_cty.toSignedness(dest_info.signedness);
45374531 need_bitcasts = wrap_cty.?.tag() == .zig_i128;
4538 info_ty_pl.data -= 1;
4539 info_ty_pl.data %= @intCast(u16, f.byteSize(elem_cty) * 8);
4540 info_ty_pl.data += 1;
4532 bits -= 1;
4533 bits %= @intCast(u16, f.byteSize(elem_cty) * 8);
4534 bits += 1;
45414535 }
45424536 try writer.writeAll(" = ");
45434537 if (need_bitcasts) {
......@@ -4546,7 +4540,7 @@ fn bitcast(f: *Function, dest_ty: Type, operand: CValue, operand_ty: Type) !Loca
45464540 try writer.writeByte('(');
45474541 }
45484542 try writer.writeAll("zig_wrap_");
4549 const info_ty = Type.initPayload(&info_ty_pl.base);
4543 const info_ty = try mod.intType(dest_info.signedness, bits);
45504544 if (wrap_cty) |cty|
45514545 try f.object.dg.renderCTypeForBuiltinFnName(writer, cty)
45524546 else
......@@ -4622,8 +4616,9 @@ fn airFence(f: *Function, inst: Air.Inst.Index) !CValue {
46224616}
46234617
46244618fn airUnreach(f: *Function) !CValue {
4619 const mod = f.object.dg.module;
46254620 // Not even allowed to call unreachable in a naked function.
4626 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention() == .Naked) return .none;
4621 if (f.object.dg.decl) |decl| if (decl.ty.fnCallingConvention(mod) == .Naked) return .none;
46274622
46284623 try f.object.writer().writeAll("zig_unreachable();\n");
46294624 return .none;
......@@ -4657,6 +4652,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
46574652 try writer.writeAll(") ");
46584653
46594654 try genBodyResolveState(f, inst, liveness_condbr.then_deaths, then_body, false);
4655 try writer.writeByte('\n');
46604656
46614657 // We don't need to use `genBodyResolveState` for the else block, because this instruction is
46624658 // noreturn so must terminate a body, therefore we don't need to leave `value_map` or
......@@ -4675,19 +4671,20 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
46754671}
46764672
46774673fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4674 const mod = f.object.dg.module;
46784675 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
46794676 const condition = try f.resolveInst(pl_op.operand);
46804677 try reap(f, inst, &.{pl_op.operand});
4681 const condition_ty = f.air.typeOf(pl_op.operand);
4678 const condition_ty = f.typeOf(pl_op.operand);
46824679 const switch_br = f.air.extraData(Air.SwitchBr, pl_op.payload);
46834680 const writer = f.object.writer();
46844681
46854682 try writer.writeAll("switch (");
4686 if (condition_ty.zigTypeTag() == .Bool) {
4683 if (condition_ty.zigTypeTag(mod) == .Bool) {
46874684 try writer.writeByte('(');
46884685 try f.renderType(writer, Type.u1);
46894686 try writer.writeByte(')');
4690 } else if (condition_ty.isPtrAtRuntime()) {
4687 } else if (condition_ty.isPtrAtRuntime(mod)) {
46914688 try writer.writeByte('(');
46924689 try f.renderType(writer, Type.usize);
46934690 try writer.writeByte(')');
......@@ -4714,12 +4711,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
47144711 for (items) |item| {
47154712 try f.object.indent_writer.insertNewline();
47164713 try writer.writeAll("case ");
4717 if (condition_ty.isPtrAtRuntime()) {
4714 if (condition_ty.isPtrAtRuntime(mod)) {
47184715 try writer.writeByte('(');
47194716 try f.renderType(writer, Type.usize);
47204717 try writer.writeByte(')');
47214718 }
4722 try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other);
4719 try f.object.dg.renderValue(writer, condition_ty, (try f.air.value(item, mod)).?, .Other);
47234720 try writer.writeByte(':');
47244721 }
47254722 try writer.writeByte(' ');
......@@ -4764,6 +4761,7 @@ fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool {
47644761}
47654762
47664763fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4764 const mod = f.object.dg.module;
47674765 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
47684766 const extra = f.air.extraData(Air.Asm, ty_pl.payload);
47694767 const is_volatile = @truncate(u1, extra.data.flags >> 31) != 0;
......@@ -4777,8 +4775,8 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
47774775
47784776 const result = result: {
47794777 const writer = f.object.writer();
4780 const inst_ty = f.air.typeOfIndex(inst);
4781 const local = if (inst_ty.hasRuntimeBitsIgnoreComptime()) local: {
4778 const inst_ty = f.typeOfIndex(inst);
4779 const local = if (inst_ty.hasRuntimeBitsIgnoreComptime(mod)) local: {
47824780 const local = try f.allocLocal(inst, inst_ty);
47834781 if (f.wantSafety()) {
47844782 try f.writeCValue(writer, local, .Other);
......@@ -4807,7 +4805,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48074805
48084806 const is_reg = constraint[1] == '{';
48094807 if (is_reg) {
4810 const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType();
4808 const output_ty = if (output == .none) inst_ty else f.typeOf(output).childType(mod);
48114809 try writer.writeAll("register ");
48124810 const alignment = 0;
48134811 const local_value = try f.allocLocalValue(output_ty, alignment);
......@@ -4840,7 +4838,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48404838 const is_reg = constraint[0] == '{';
48414839 const input_val = try f.resolveInst(input);
48424840 if (asmInputNeedsLocal(constraint, input_val)) {
4843 const input_ty = f.air.typeOf(input);
4841 const input_ty = f.typeOf(input);
48444842 if (is_reg) try writer.writeAll("register ");
48454843 const alignment = 0;
48464844 const local_value = try f.allocLocalValue(input_ty, alignment);
......@@ -5025,6 +5023,7 @@ fn airIsNull(
50255023 operator: []const u8,
50265024 is_ptr: bool,
50275025) !CValue {
5026 const mod = f.object.dg.module;
50285027 const un_op = f.air.instructions.items(.data)[inst].un_op;
50295028
50305029 const writer = f.object.writer();
......@@ -5040,23 +5039,22 @@ fn airIsNull(
50405039 try f.writeCValue(writer, operand, .Other);
50415040 }
50425041
5043 const operand_ty = f.air.typeOf(un_op);
5044 const optional_ty = if (is_ptr) operand_ty.childType() else operand_ty;
5045 var payload_buf: Type.Payload.ElemType = undefined;
5046 const payload_ty = optional_ty.optionalChild(&payload_buf);
5047 var slice_ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
5042 const operand_ty = f.typeOf(un_op);
5043 const optional_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
5044 const payload_ty = optional_ty.optionalChild(mod);
50485045
5049 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime())
5046 const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod))
50505047 TypedValue{ .ty = Type.bool, .val = Value.true }
5051 else if (optional_ty.isPtrLikeOptional())
5048 else if (optional_ty.isPtrLikeOptional(mod))
50525049 // operand is a regular pointer, test `operand !=/== NULL`
5053 TypedValue{ .ty = optional_ty, .val = Value.null }
5054 else if (payload_ty.zigTypeTag() == .ErrorSet)
5055 TypedValue{ .ty = payload_ty, .val = Value.zero }
5056 else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload()) rhs: {
5050 TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) }
5051 else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
5052 TypedValue{ .ty = Type.err_int, .val = try mod.intValue(Type.err_int, 0) }
5053 else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
50575054 try writer.writeAll(".ptr");
5058 const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf);
5059 break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null };
5055 const slice_ptr_ty = payload_ty.slicePtrFieldType(mod);
5056 const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern());
5057 break :rhs TypedValue{ .ty = opt_slice_ptr_ty, .val = try mod.nullValue(opt_slice_ptr_ty) };
50605058 } else rhs: {
50615059 try writer.writeAll(".is_null");
50625060 break :rhs TypedValue{ .ty = Type.bool, .val = Value.true };
......@@ -5070,24 +5068,24 @@ fn airIsNull(
50705068}
50715069
50725070fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
5071 const mod = f.object.dg.module;
50735072 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
50745073
50755074 const operand = try f.resolveInst(ty_op.operand);
50765075 try reap(f, inst, &.{ty_op.operand});
5077 const opt_ty = f.air.typeOf(ty_op.operand);
5076 const opt_ty = f.typeOf(ty_op.operand);
50785077
5079 var buf: Type.Payload.ElemType = undefined;
5080 const payload_ty = opt_ty.optionalChild(&buf);
5078 const payload_ty = opt_ty.optionalChild(mod);
50815079
5082 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
5080 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
50835081 return .none;
50845082 }
50855083
5086 const inst_ty = f.air.typeOfIndex(inst);
5084 const inst_ty = f.typeOfIndex(inst);
50875085 const writer = f.object.writer();
50885086 const local = try f.allocLocal(inst, inst_ty);
50895087
5090 if (opt_ty.optionalReprIsPayload()) {
5088 if (opt_ty.optionalReprIsPayload(mod)) {
50915089 try f.writeCValue(writer, local, .Other);
50925090 try writer.writeAll(" = ");
50935091 try f.writeCValue(writer, operand, .Other);
......@@ -5104,23 +5102,24 @@ fn airOptionalPayload(f: *Function, inst: Air.Inst.Index) !CValue {
51045102}
51055103
51065104fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5105 const mod = f.object.dg.module;
51075106 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
51085107
51095108 const writer = f.object.writer();
51105109 const operand = try f.resolveInst(ty_op.operand);
51115110 try reap(f, inst, &.{ty_op.operand});
5112 const ptr_ty = f.air.typeOf(ty_op.operand);
5113 const opt_ty = ptr_ty.childType();
5114 const inst_ty = f.air.typeOfIndex(inst);
5111 const ptr_ty = f.typeOf(ty_op.operand);
5112 const opt_ty = ptr_ty.childType(mod);
5113 const inst_ty = f.typeOfIndex(inst);
51155114
5116 if (!inst_ty.childType().hasRuntimeBitsIgnoreComptime()) {
5115 if (!inst_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod)) {
51175116 return .{ .undef = inst_ty };
51185117 }
51195118
51205119 const local = try f.allocLocal(inst, inst_ty);
51215120 try f.writeCValue(writer, local, .Other);
51225121
5123 if (opt_ty.optionalReprIsPayload()) {
5122 if (opt_ty.optionalReprIsPayload(mod)) {
51245123 // the operand is just a regular pointer, no need to do anything special.
51255124 // *?*T -> **T and ?*T -> *T are **T -> **T and *T -> *T in C
51265125 try writer.writeAll(" = ");
......@@ -5134,17 +5133,18 @@ fn airOptionalPayloadPtr(f: *Function, inst: Air.Inst.Index) !CValue {
51345133}
51355134
51365135fn airOptionalPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5136 const mod = f.object.dg.module;
51375137 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
51385138 const writer = f.object.writer();
51395139 const operand = try f.resolveInst(ty_op.operand);
51405140 try reap(f, inst, &.{ty_op.operand});
5141 const operand_ty = f.air.typeOf(ty_op.operand);
5141 const operand_ty = f.typeOf(ty_op.operand);
51425142
5143 const opt_ty = operand_ty.elemType();
5143 const opt_ty = operand_ty.childType(mod);
51445144
5145 const inst_ty = f.air.typeOfIndex(inst);
5145 const inst_ty = f.typeOfIndex(inst);
51465146
5147 if (opt_ty.optionalReprIsPayload()) {
5147 if (opt_ty.optionalReprIsPayload(mod)) {
51485148 if (f.liveness.isUnused(inst)) {
51495149 return .none;
51505150 }
......@@ -5179,48 +5179,49 @@ fn fieldLocation(
51795179 container_ty: Type,
51805180 field_ptr_ty: Type,
51815181 field_index: u32,
5182 target: std.Target,
5182 mod: *Module,
51835183) union(enum) {
51845184 begin: void,
51855185 field: CValue,
51865186 byte_offset: u32,
51875187 end: void,
51885188} {
5189 return switch (container_ty.zigTypeTag()) {
5190 .Struct => switch (container_ty.containerLayout()) {
5191 .Auto, .Extern => for (field_index..container_ty.structFieldCount()) |next_field_index| {
5192 if (container_ty.structFieldIsComptime(next_field_index)) continue;
5193 const field_ty = container_ty.structFieldType(next_field_index);
5194 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
5195
5196 break .{ .field = if (container_ty.isSimpleTuple())
5189 const ip = &mod.intern_pool;
5190 return switch (container_ty.zigTypeTag(mod)) {
5191 .Struct => switch (container_ty.containerLayout(mod)) {
5192 .Auto, .Extern => for (field_index..container_ty.structFieldCount(mod)) |next_field_index| {
5193 if (container_ty.structFieldIsComptime(next_field_index, mod)) continue;
5194 const field_ty = container_ty.structFieldType(next_field_index, mod);
5195 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
5196
5197 break .{ .field = if (container_ty.isSimpleTuple(mod))
51975198 .{ .field = next_field_index }
51985199 else
5199 .{ .identifier = container_ty.structFieldName(next_field_index) } };
5200 } else if (container_ty.hasRuntimeBitsIgnoreComptime()) .end else .begin,
5201 .Packed => if (field_ptr_ty.ptrInfo().data.host_size == 0)
5202 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, target) }
5200 .{ .identifier = ip.stringToSlice(container_ty.structFieldName(next_field_index, mod)) } };
5201 } else if (container_ty.hasRuntimeBitsIgnoreComptime(mod)) .end else .begin,
5202 .Packed => if (field_ptr_ty.ptrInfo(mod).host_size == 0)
5203 .{ .byte_offset = container_ty.packedStructFieldByteOffset(field_index, mod) }
52035204 else
52045205 .begin,
52055206 },
5206 .Union => switch (container_ty.containerLayout()) {
5207 .Union => switch (container_ty.containerLayout(mod)) {
52075208 .Auto, .Extern => {
5208 const field_ty = container_ty.structFieldType(field_index);
5209 if (!field_ty.hasRuntimeBitsIgnoreComptime())
5210 return if (container_ty.unionTagTypeSafety() != null and
5211 !container_ty.unionHasAllZeroBitFieldTypes())
5209 const field_ty = container_ty.structFieldType(field_index, mod);
5210 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod))
5211 return if (container_ty.unionTagTypeSafety(mod) != null and
5212 !container_ty.unionHasAllZeroBitFieldTypes(mod))
52125213 .{ .field = .{ .identifier = "payload" } }
52135214 else
52145215 .begin;
5215 const field_name = container_ty.unionFields().keys()[field_index];
5216 return .{ .field = if (container_ty.unionTagTypeSafety()) |_|
5217 .{ .payload_identifier = field_name }
5216 const field_name = container_ty.unionFields(mod).keys()[field_index];
5217 return .{ .field = if (container_ty.unionTagTypeSafety(mod)) |_|
5218 .{ .payload_identifier = ip.stringToSlice(field_name) }
52185219 else
5219 .{ .identifier = field_name } };
5220 .{ .identifier = ip.stringToSlice(field_name) } };
52205221 },
52215222 .Packed => .begin,
52225223 },
5223 .Pointer => switch (container_ty.ptrSize()) {
5224 .Pointer => switch (container_ty.ptrSize(mod)) {
52245225 .Slice => switch (field_index) {
52255226 0 => .{ .field = .{ .identifier = "ptr" } },
52265227 1 => .{ .field = .{ .identifier = "len" } },
......@@ -5238,7 +5239,7 @@ fn airStructFieldPtr(f: *Function, inst: Air.Inst.Index) !CValue {
52385239
52395240 const container_ptr_val = try f.resolveInst(extra.struct_operand);
52405241 try reap(f, inst, &.{extra.struct_operand});
5241 const container_ptr_ty = f.air.typeOf(extra.struct_operand);
5242 const container_ptr_ty = f.typeOf(extra.struct_operand);
52425243 return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, extra.field_index);
52435244}
52445245
......@@ -5247,19 +5248,19 @@ fn airStructFieldPtrIndex(f: *Function, inst: Air.Inst.Index, index: u8) !CValue
52475248
52485249 const container_ptr_val = try f.resolveInst(ty_op.operand);
52495250 try reap(f, inst, &.{ty_op.operand});
5250 const container_ptr_ty = f.air.typeOf(ty_op.operand);
5251 const container_ptr_ty = f.typeOf(ty_op.operand);
52515252 return fieldPtr(f, inst, container_ptr_ty, container_ptr_val, index);
52525253}
52535254
52545255fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
5256 const mod = f.object.dg.module;
52555257 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
52565258 const extra = f.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
52575259
5258 const target = f.object.dg.module.getTarget();
5259 const container_ptr_ty = f.air.typeOfIndex(inst);
5260 const container_ty = container_ptr_ty.childType();
5260 const container_ptr_ty = f.typeOfIndex(inst);
5261 const container_ty = container_ptr_ty.childType(mod);
52615262
5262 const field_ptr_ty = f.air.typeOf(extra.field_ptr);
5263 const field_ptr_ty = f.typeOf(extra.field_ptr);
52635264 const field_ptr_val = try f.resolveInst(extra.field_ptr);
52645265 try reap(f, inst, &.{extra.field_ptr});
52655266
......@@ -5270,12 +5271,10 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
52705271 try f.renderType(writer, container_ptr_ty);
52715272 try writer.writeByte(')');
52725273
5273 switch (fieldLocation(container_ty, field_ptr_ty, extra.field_index, target)) {
5274 switch (fieldLocation(container_ty, field_ptr_ty, extra.field_index, mod)) {
52745275 .begin => try f.writeCValue(writer, field_ptr_val, .Initializer),
52755276 .field => |field| {
5276 var u8_ptr_pl = field_ptr_ty.ptrInfo();
5277 u8_ptr_pl.data.pointee_type = Type.u8;
5278 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
5277 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
52795278
52805279 try writer.writeAll("((");
52815280 try f.renderType(writer, u8_ptr_ty);
......@@ -5288,15 +5287,9 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
52885287 try writer.writeAll("))");
52895288 },
52905289 .byte_offset => |byte_offset| {
5291 var u8_ptr_pl = field_ptr_ty.ptrInfo();
5292 u8_ptr_pl.data.pointee_type = Type.u8;
5293 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
5290 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
52945291
5295 var byte_offset_pl = Value.Payload.U64{
5296 .base = .{ .tag = .int_u64 },
5297 .data = byte_offset,
5298 };
5299 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
5292 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
53005293
53015294 try writer.writeAll("((");
53025295 try f.renderType(writer, u8_ptr_ty);
......@@ -5306,7 +5299,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
53065299 },
53075300 .end => {
53085301 try f.writeCValue(writer, field_ptr_val, .Other);
5309 try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, Value.one)});
5302 try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
53105303 },
53115304 }
53125305
......@@ -5321,9 +5314,9 @@ fn fieldPtr(
53215314 container_ptr_val: CValue,
53225315 field_index: u32,
53235316) !CValue {
5324 const target = f.object.dg.module.getTarget();
5325 const container_ty = container_ptr_ty.elemType();
5326 const field_ptr_ty = f.air.typeOfIndex(inst);
5317 const mod = f.object.dg.module;
5318 const container_ty = container_ptr_ty.childType(mod);
5319 const field_ptr_ty = f.typeOfIndex(inst);
53275320
53285321 // Ensure complete type definition is visible before accessing fields.
53295322 _ = try f.typeToIndex(container_ty, .complete);
......@@ -5335,22 +5328,16 @@ fn fieldPtr(
53355328 try f.renderType(writer, field_ptr_ty);
53365329 try writer.writeByte(')');
53375330
5338 switch (fieldLocation(container_ty, field_ptr_ty, field_index, target)) {
5331 switch (fieldLocation(container_ty, field_ptr_ty, field_index, mod)) {
53395332 .begin => try f.writeCValue(writer, container_ptr_val, .Initializer),
53405333 .field => |field| {
53415334 try writer.writeByte('&');
53425335 try f.writeCValueDerefMember(writer, container_ptr_val, field);
53435336 },
53445337 .byte_offset => |byte_offset| {
5345 var u8_ptr_pl = field_ptr_ty.ptrInfo();
5346 u8_ptr_pl.data.pointee_type = Type.u8;
5347 const u8_ptr_ty = Type.initPayload(&u8_ptr_pl.base);
5338 const u8_ptr_ty = try mod.adjustPtrTypeChild(field_ptr_ty, Type.u8);
53485339
5349 var byte_offset_pl = Value.Payload.U64{
5350 .base = .{ .tag = .int_u64 },
5351 .data = byte_offset,
5352 };
5353 const byte_offset_val = Value.initPayload(&byte_offset_pl.base);
5340 const byte_offset_val = try mod.intValue(Type.usize, byte_offset);
53545341
53555342 try writer.writeAll("((");
53565343 try f.renderType(writer, u8_ptr_ty);
......@@ -5361,7 +5348,7 @@ fn fieldPtr(
53615348 .end => {
53625349 try writer.writeByte('(');
53635350 try f.writeCValue(writer, container_ptr_val, .Other);
5364 try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, Value.one)});
5351 try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
53655352 },
53665353 }
53675354
......@@ -5370,58 +5357,45 @@ fn fieldPtr(
53705357}
53715358
53725359fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
5360 const mod = f.object.dg.module;
5361 const ip = &mod.intern_pool;
53735362 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
53745363 const extra = f.air.extraData(Air.StructField, ty_pl.payload).data;
53755364
5376 const inst_ty = f.air.typeOfIndex(inst);
5377 if (!inst_ty.hasRuntimeBitsIgnoreComptime()) {
5365 const inst_ty = f.typeOfIndex(inst);
5366 if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod)) {
53785367 try reap(f, inst, &.{extra.struct_operand});
53795368 return .none;
53805369 }
53815370
5382 const target = f.object.dg.module.getTarget();
53835371 const struct_byval = try f.resolveInst(extra.struct_operand);
53845372 try reap(f, inst, &.{extra.struct_operand});
5385 const struct_ty = f.air.typeOf(extra.struct_operand);
5373 const struct_ty = f.typeOf(extra.struct_operand);
53865374 const writer = f.object.writer();
53875375
53885376 // Ensure complete type definition is visible before accessing fields.
53895377 _ = try f.typeToIndex(struct_ty, .complete);
53905378
5391 const field_name: CValue = switch (struct_ty.tag()) {
5392 .tuple, .anon_struct, .@"struct" => switch (struct_ty.containerLayout()) {
5393 .Auto, .Extern => if (struct_ty.isSimpleTuple())
5379 const field_name: CValue = switch (mod.intern_pool.indexToKey(struct_ty.ip_index)) {
5380 .struct_type => switch (struct_ty.containerLayout(mod)) {
5381 .Auto, .Extern => if (struct_ty.isSimpleTuple(mod))
53945382 .{ .field = extra.field_index }
53955383 else
5396 .{ .identifier = struct_ty.structFieldName(extra.field_index) },
5384 .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) },
53975385 .Packed => {
5398 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5399 const int_info = struct_ty.intInfo(target);
5386 const struct_obj = mod.typeToStruct(struct_ty).?;
5387 const int_info = struct_ty.intInfo(mod);
54005388
5401 var bit_offset_ty_pl = Type.Payload.Bits{
5402 .base = .{ .tag = .int_unsigned },
5403 .data = Type.smallestUnsignedBits(int_info.bits - 1),
5404 };
5405 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
5389 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
54065390
5407 var bit_offset_val_pl: Value.Payload.U64 = .{
5408 .base = .{ .tag = .int_u64 },
5409 .data = struct_obj.packedFieldBitOffset(target, extra.field_index),
5410 };
5411 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
5391 const bit_offset = struct_obj.packedFieldBitOffset(mod, extra.field_index);
5392 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
54125393
5413 const field_int_signedness = if (inst_ty.isAbiInt())
5414 inst_ty.intInfo(target).signedness
5394 const field_int_signedness = if (inst_ty.isAbiInt(mod))
5395 inst_ty.intInfo(mod).signedness
54155396 else
54165397 .unsigned;
5417 var field_int_pl = Type.Payload.Bits{
5418 .base = .{ .tag = switch (field_int_signedness) {
5419 .unsigned => .int_unsigned,
5420 .signed => .int_signed,
5421 } },
5422 .data = @intCast(u16, inst_ty.bitSize(target)),
5423 };
5424 const field_int_ty = Type.initPayload(&field_int_pl.base);
5398 const field_int_ty = try mod.intType(field_int_signedness, @intCast(u16, inst_ty.bitSize(mod)));
54255399
54265400 const temp_local = try f.allocLocal(inst, field_int_ty);
54275401 try f.writeCValue(writer, temp_local, .Other);
......@@ -5432,18 +5406,18 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
54325406 try writer.writeByte(')');
54335407 const cant_cast = int_info.bits > 64;
54345408 if (cant_cast) {
5435 if (field_int_ty.bitSize(target) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
5409 if (field_int_ty.bitSize(mod) > 64) return f.fail("TODO: C backend: implement casting between types > 64 bits", .{});
54365410 try writer.writeAll("zig_lo_");
54375411 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
54385412 try writer.writeByte('(');
54395413 }
5440 if (bit_offset_val_pl.data > 0) {
5414 if (bit_offset > 0) {
54415415 try writer.writeAll("zig_shr_");
54425416 try f.object.dg.renderTypeForBuiltinFnName(writer, struct_ty);
54435417 try writer.writeByte('(');
54445418 }
54455419 try f.writeCValue(writer, struct_byval, .Other);
5446 if (bit_offset_val_pl.data > 0) {
5420 if (bit_offset > 0) {
54475421 try writer.writeAll(", ");
54485422 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
54495423 try writer.writeByte(')');
......@@ -5465,36 +5439,46 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
54655439 return local;
54665440 },
54675441 },
5468 .@"union", .union_safety_tagged, .union_tagged => if (struct_ty.containerLayout() == .Packed) {
5469 const operand_lval = if (struct_byval == .constant) blk: {
5470 const operand_local = try f.allocLocal(inst, struct_ty);
5471 try f.writeCValue(writer, operand_local, .Other);
5472 try writer.writeAll(" = ");
5473 try f.writeCValue(writer, struct_byval, .Initializer);
5474 try writer.writeAll(";\n");
5475 break :blk operand_local;
5476 } else struct_byval;
54775442
5478 const local = try f.allocLocal(inst, inst_ty);
5479 try writer.writeAll("memcpy(&");
5480 try f.writeCValue(writer, local, .Other);
5481 try writer.writeAll(", &");
5482 try f.writeCValue(writer, operand_lval, .Other);
5483 try writer.writeAll(", sizeof(");
5484 try f.renderType(writer, inst_ty);
5485 try writer.writeAll("));\n");
5443 .anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 0)
5444 .{ .field = extra.field_index }
5445 else
5446 .{ .identifier = ip.stringToSlice(struct_ty.structFieldName(extra.field_index, mod)) },
5447
5448 .union_type => |union_type| field_name: {
5449 const union_obj = mod.unionPtr(union_type.index);
5450 if (union_obj.layout == .Packed) {
5451 const operand_lval = if (struct_byval == .constant) blk: {
5452 const operand_local = try f.allocLocal(inst, struct_ty);
5453 try f.writeCValue(writer, operand_local, .Other);
5454 try writer.writeAll(" = ");
5455 try f.writeCValue(writer, struct_byval, .Initializer);
5456 try writer.writeAll(";\n");
5457 break :blk operand_local;
5458 } else struct_byval;
54865459
5487 if (struct_byval == .constant) {
5488 try freeLocal(f, inst, operand_lval.new_local, 0);
5489 }
5460 const local = try f.allocLocal(inst, inst_ty);
5461 try writer.writeAll("memcpy(&");
5462 try f.writeCValue(writer, local, .Other);
5463 try writer.writeAll(", &");
5464 try f.writeCValue(writer, operand_lval, .Other);
5465 try writer.writeAll(", sizeof(");
5466 try f.renderType(writer, inst_ty);
5467 try writer.writeAll("));\n");
54905468
5491 return local;
5492 } else field_name: {
5493 const name = struct_ty.unionFields().keys()[extra.field_index];
5494 break :field_name if (struct_ty.unionTagTypeSafety()) |_|
5495 .{ .payload_identifier = name }
5496 else
5497 .{ .identifier = name };
5469 if (struct_byval == .constant) {
5470 try freeLocal(f, inst, operand_lval.new_local, 0);
5471 }
5472
5473 return local;
5474 } else {
5475 const name = union_obj.fields.keys()[extra.field_index];
5476 break :field_name if (union_type.hasTag()) .{
5477 .payload_identifier = ip.stringToSlice(name),
5478 } else .{
5479 .identifier = ip.stringToSlice(name),
5480 };
5481 }
54985482 },
54995483 else => unreachable,
55005484 };
......@@ -5511,20 +5495,21 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue {
55115495/// *(E!T) -> E
55125496/// Note that the result is never a pointer.
55135497fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5498 const mod = f.object.dg.module;
55145499 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
55155500
5516 const inst_ty = f.air.typeOfIndex(inst);
5501 const inst_ty = f.typeOfIndex(inst);
55175502 const operand = try f.resolveInst(ty_op.operand);
5518 const operand_ty = f.air.typeOf(ty_op.operand);
5503 const operand_ty = f.typeOf(ty_op.operand);
55195504 try reap(f, inst, &.{ty_op.operand});
55205505
5521 const operand_is_ptr = operand_ty.zigTypeTag() == .Pointer;
5522 const error_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
5523 const error_ty = error_union_ty.errorUnionSet();
5524 const payload_ty = error_union_ty.errorUnionPayload();
5506 const operand_is_ptr = operand_ty.zigTypeTag(mod) == .Pointer;
5507 const error_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
5508 const error_ty = error_union_ty.errorUnionSet(mod);
5509 const payload_ty = error_union_ty.errorUnionPayload(mod);
55255510 const local = try f.allocLocal(inst, inst_ty);
55265511
5527 if (!payload_ty.hasRuntimeBits() and operand == .local and operand.local == local.new_local) {
5512 if (!payload_ty.hasRuntimeBits(mod) and operand == .local and operand.local == local.new_local) {
55285513 // The store will be 'x = x'; elide it.
55295514 return local;
55305515 }
......@@ -5533,32 +5518,33 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
55335518 try f.writeCValue(writer, local, .Other);
55345519 try writer.writeAll(" = ");
55355520
5536 if (!payload_ty.hasRuntimeBits()) {
5521 if (!payload_ty.hasRuntimeBits(mod)) {
55375522 try f.writeCValue(writer, operand, .Other);
55385523 } else {
5539 if (!error_ty.errorSetIsEmpty())
5524 if (!error_ty.errorSetIsEmpty(mod))
55405525 if (operand_is_ptr)
55415526 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
55425527 else
55435528 try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
55445529 else
5545 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
5530 try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Initializer);
55465531 }
55475532 try writer.writeAll(";\n");
55485533 return local;
55495534}
55505535
55515536fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValue {
5537 const mod = f.object.dg.module;
55525538 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
55535539
5554 const inst_ty = f.air.typeOfIndex(inst);
5540 const inst_ty = f.typeOfIndex(inst);
55555541 const operand = try f.resolveInst(ty_op.operand);
55565542 try reap(f, inst, &.{ty_op.operand});
5557 const operand_ty = f.air.typeOf(ty_op.operand);
5558 const error_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;
5543 const operand_ty = f.typeOf(ty_op.operand);
5544 const error_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
55595545
55605546 const writer = f.object.writer();
5561 if (!error_union_ty.errorUnionPayload().hasRuntimeBits()) {
5547 if (!error_union_ty.errorUnionPayload(mod).hasRuntimeBits(mod)) {
55625548 if (!is_ptr) return .none;
55635549
55645550 const local = try f.allocLocal(inst, inst_ty);
......@@ -5584,11 +5570,12 @@ fn airUnwrapErrUnionPay(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !CValu
55845570}
55855571
55865572fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
5573 const mod = f.object.dg.module;
55875574 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
55885575
5589 const inst_ty = f.air.typeOfIndex(inst);
5590 const repr_is_payload = inst_ty.optionalReprIsPayload();
5591 const payload_ty = f.air.typeOf(ty_op.operand);
5576 const inst_ty = f.typeOfIndex(inst);
5577 const repr_is_payload = inst_ty.optionalReprIsPayload(mod);
5578 const payload_ty = f.typeOf(ty_op.operand);
55925579 const payload = try f.resolveInst(ty_op.operand);
55935580 try reap(f, inst, &.{ty_op.operand});
55945581
......@@ -5615,12 +5602,13 @@ fn airWrapOptional(f: *Function, inst: Air.Inst.Index) !CValue {
56155602}
56165603
56175604fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
5605 const mod = f.object.dg.module;
56185606 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
56195607
5620 const inst_ty = f.air.typeOfIndex(inst);
5621 const payload_ty = inst_ty.errorUnionPayload();
5622 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime();
5623 const err_ty = inst_ty.errorUnionSet();
5608 const inst_ty = f.typeOfIndex(inst);
5609 const payload_ty = inst_ty.errorUnionPayload(mod);
5610 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5611 const err_ty = inst_ty.errorUnionSet(mod);
56245612 const err = try f.resolveInst(ty_op.operand);
56255613 try reap(f, inst, &.{ty_op.operand});
56265614
......@@ -5653,19 +5641,20 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
56535641}
56545642
56555643fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
5644 const mod = f.object.dg.module;
56565645 const writer = f.object.writer();
56575646 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
56585647 const operand = try f.resolveInst(ty_op.operand);
5659 const error_union_ty = f.air.typeOf(ty_op.operand).childType();
5648 const error_union_ty = f.typeOf(ty_op.operand).childType(mod);
56605649
5661 const error_ty = error_union_ty.errorUnionSet();
5662 const payload_ty = error_union_ty.errorUnionPayload();
5650 const error_ty = error_union_ty.errorUnionSet(mod);
5651 const payload_ty = error_union_ty.errorUnionPayload(mod);
56635652
56645653 // First, set the non-error value.
5665 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
5654 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
56665655 try f.writeCValueDeref(writer, operand);
56675656 try writer.writeAll(" = ");
5668 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
5657 try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
56695658 try writer.writeAll(";\n ");
56705659
56715660 return operand;
......@@ -5673,13 +5662,13 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
56735662 try reap(f, inst, &.{ty_op.operand});
56745663 try f.writeCValueDeref(writer, operand);
56755664 try writer.writeAll(".error = ");
5676 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
5665 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
56775666 try writer.writeAll(";\n");
56785667
56795668 // Then return the payload pointer (only if it is used)
56805669 if (f.liveness.isUnused(inst)) return .none;
56815670
5682 const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));
5671 const local = try f.allocLocal(inst, f.typeOfIndex(inst));
56835672 try f.writeCValue(writer, local, .Other);
56845673 try writer.writeAll(" = &(");
56855674 try f.writeCValueDeref(writer, operand);
......@@ -5703,13 +5692,14 @@ fn airSaveErrReturnTraceIndex(f: *Function, inst: Air.Inst.Index) !CValue {
57035692}
57045693
57055694fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
5695 const mod = f.object.dg.module;
57065696 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
57075697
5708 const inst_ty = f.air.typeOfIndex(inst);
5709 const payload_ty = inst_ty.errorUnionPayload();
5698 const inst_ty = f.typeOfIndex(inst);
5699 const payload_ty = inst_ty.errorUnionPayload(mod);
57105700 const payload = try f.resolveInst(ty_op.operand);
5711 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime();
5712 const err_ty = inst_ty.errorUnionSet();
5701 const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(mod);
5702 const err_ty = inst_ty.errorUnionSet(mod);
57135703 try reap(f, inst, &.{ty_op.operand});
57145704
57155705 const writer = f.object.writer();
......@@ -5728,29 +5718,30 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
57285718 else
57295719 try f.writeCValueMember(writer, local, .{ .identifier = "error" });
57305720 try a.assign(f, writer);
5731 try f.object.dg.renderValue(writer, err_ty, Value.zero, .Other);
5721 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
57325722 try a.end(f, writer);
57335723 }
57345724 return local;
57355725}
57365726
57375727fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const u8) !CValue {
5728 const mod = f.object.dg.module;
57385729 const un_op = f.air.instructions.items(.data)[inst].un_op;
57395730
57405731 const writer = f.object.writer();
57415732 const operand = try f.resolveInst(un_op);
57425733 try reap(f, inst, &.{un_op});
5743 const operand_ty = f.air.typeOf(un_op);
5734 const operand_ty = f.typeOf(un_op);
57445735 const local = try f.allocLocal(inst, Type.bool);
5745 const err_union_ty = if (is_ptr) operand_ty.childType() else operand_ty;
5746 const payload_ty = err_union_ty.errorUnionPayload();
5747 const error_ty = err_union_ty.errorUnionSet();
5736 const err_union_ty = if (is_ptr) operand_ty.childType(mod) else operand_ty;
5737 const payload_ty = err_union_ty.errorUnionPayload(mod);
5738 const error_ty = err_union_ty.errorUnionSet(mod);
57485739
57495740 try f.writeCValue(writer, local, .Other);
57505741 try writer.writeAll(" = ");
57515742
5752 if (!error_ty.errorSetIsEmpty())
5753 if (payload_ty.hasRuntimeBits())
5743 if (!error_ty.errorSetIsEmpty(mod))
5744 if (payload_ty.hasRuntimeBits(mod))
57545745 if (is_ptr)
57555746 try f.writeCValueDerefMember(writer, operand, .{ .identifier = "error" })
57565747 else
......@@ -5758,42 +5749,40 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
57585749 else
57595750 try f.writeCValue(writer, operand, .Other)
57605751 else
5761 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
5752 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
57625753 try writer.writeByte(' ');
57635754 try writer.writeAll(operator);
57645755 try writer.writeByte(' ');
5765 try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
5756 try f.object.dg.renderValue(writer, Type.err_int, try mod.intValue(Type.err_int, 0), .Other);
57665757 try writer.writeAll(";\n");
57675758 return local;
57685759}
57695760
57705761fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
5762 const mod = f.object.dg.module;
57715763 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
57725764
57735765 const operand = try f.resolveInst(ty_op.operand);
57745766 try reap(f, inst, &.{ty_op.operand});
5775 const inst_ty = f.air.typeOfIndex(inst);
5767 const inst_ty = f.typeOfIndex(inst);
57765768 const writer = f.object.writer();
57775769 const local = try f.allocLocal(inst, inst_ty);
5778 const array_ty = f.air.typeOf(ty_op.operand).childType();
5770 const array_ty = f.typeOf(ty_op.operand).childType(mod);
57795771
57805772 try f.writeCValueMember(writer, local, .{ .identifier = "ptr" });
57815773 try writer.writeAll(" = ");
57825774 // Unfortunately, C does not support any equivalent to
57835775 // &(*(void *)p)[0], although LLVM does via GetElementPtr
57845776 if (operand == .undef) {
5785 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
5786 try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(&buf) }, .Initializer);
5787 } else if (array_ty.hasRuntimeBitsIgnoreComptime()) {
5777 try f.writeCValue(writer, .{ .undef = inst_ty.slicePtrFieldType(mod) }, .Initializer);
5778 } else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
57885779 try writer.writeAll("&(");
57895780 try f.writeCValueDeref(writer, operand);
5790 try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
5781 try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))});
57915782 } else try f.writeCValue(writer, operand, .Initializer);
57925783 try writer.writeAll("; ");
57935784
5794 const array_len = array_ty.arrayLen();
5795 var len_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = array_len };
5796 const len_val = Value.initPayload(&len_pl.base);
5785 const len_val = try mod.intValue(Type.usize, array_ty.arrayLen(mod));
57975786 try f.writeCValueMember(writer, local, .{ .identifier = "len" });
57985787 try writer.print(" = {};\n", .{try f.fmtIntLiteral(Type.usize, len_val)});
57995788
......@@ -5801,19 +5790,20 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
58015790}
58025791
58035792fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
5793 const mod = f.object.dg.module;
58045794 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
58055795
5806 const inst_ty = f.air.typeOfIndex(inst);
5796 const inst_ty = f.typeOfIndex(inst);
58075797 const operand = try f.resolveInst(ty_op.operand);
58085798 try reap(f, inst, &.{ty_op.operand});
5809 const operand_ty = f.air.typeOf(ty_op.operand);
5799 const operand_ty = f.typeOf(ty_op.operand);
58105800 const target = f.object.dg.module.getTarget();
58115801 const operation = if (inst_ty.isRuntimeFloat() and operand_ty.isRuntimeFloat())
58125802 if (inst_ty.floatBits(target) < operand_ty.floatBits(target)) "trunc" else "extend"
5813 else if (inst_ty.isInt() and operand_ty.isRuntimeFloat())
5814 if (inst_ty.isSignedInt()) "fix" else "fixuns"
5815 else if (inst_ty.isRuntimeFloat() and operand_ty.isInt())
5816 if (operand_ty.isSignedInt()) "float" else "floatun"
5803 else if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat())
5804 if (inst_ty.isSignedInt(mod)) "fix" else "fixuns"
5805 else if (inst_ty.isRuntimeFloat() and operand_ty.isInt(mod))
5806 if (operand_ty.isSignedInt(mod)) "float" else "floatun"
58175807 else
58185808 unreachable;
58195809
......@@ -5822,19 +5812,19 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
58225812 try f.writeCValue(writer, local, .Other);
58235813
58245814 try writer.writeAll(" = ");
5825 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {
5815 if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) {
58265816 try writer.writeAll("zig_wrap_");
58275817 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
58285818 try writer.writeByte('(');
58295819 }
58305820 try writer.writeAll("zig_");
58315821 try writer.writeAll(operation);
5832 try writer.writeAll(compilerRtAbbrev(operand_ty, target));
5833 try writer.writeAll(compilerRtAbbrev(inst_ty, target));
5822 try writer.writeAll(compilerRtAbbrev(operand_ty, mod));
5823 try writer.writeAll(compilerRtAbbrev(inst_ty, mod));
58345824 try writer.writeByte('(');
58355825 try f.writeCValue(writer, operand, .FunctionArgument);
58365826 try writer.writeByte(')');
5837 if (inst_ty.isInt() and operand_ty.isRuntimeFloat()) {
5827 if (inst_ty.isInt(mod) and operand_ty.isRuntimeFloat()) {
58385828 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
58395829 try writer.writeByte(')');
58405830 }
......@@ -5843,12 +5833,13 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue {
58435833}
58445834
58455835fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
5836 const mod = f.object.dg.module;
58465837 const un_op = f.air.instructions.items(.data)[inst].un_op;
58475838
58485839 const operand = try f.resolveInst(un_op);
5849 const operand_ty = f.air.typeOf(un_op);
5840 const operand_ty = f.typeOf(un_op);
58505841 try reap(f, inst, &.{un_op});
5851 const inst_ty = f.air.typeOfIndex(inst);
5842 const inst_ty = f.typeOfIndex(inst);
58525843 const writer = f.object.writer();
58535844 const local = try f.allocLocal(inst, inst_ty);
58545845 try f.writeCValue(writer, local, .Other);
......@@ -5856,7 +5847,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
58565847 try writer.writeAll(" = (");
58575848 try f.renderType(writer, inst_ty);
58585849 try writer.writeByte(')');
5859 if (operand_ty.isSlice()) {
5850 if (operand_ty.isSlice(mod)) {
58605851 try f.writeCValueMember(writer, operand, .{ .identifier = "len" });
58615852 } else {
58625853 try f.writeCValue(writer, operand, .Other);
......@@ -5871,14 +5862,15 @@ fn airUnBuiltinCall(
58715862 operation: []const u8,
58725863 info: BuiltinInfo,
58735864) !CValue {
5865 const mod = f.object.dg.module;
58745866 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
58755867
58765868 const operand = try f.resolveInst(ty_op.operand);
58775869 try reap(f, inst, &.{ty_op.operand});
5878 const inst_ty = f.air.typeOfIndex(inst);
5879 const inst_scalar_ty = inst_ty.scalarType();
5880 const operand_ty = f.air.typeOf(ty_op.operand);
5881 const scalar_ty = operand_ty.scalarType();
5870 const inst_ty = f.typeOfIndex(inst);
5871 const inst_scalar_ty = inst_ty.scalarType(mod);
5872 const operand_ty = f.typeOf(ty_op.operand);
5873 const scalar_ty = operand_ty.scalarType(mod);
58825874
58835875 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
58845876 const ref_ret = inst_scalar_cty.tag() == .array;
......@@ -5914,9 +5906,10 @@ fn airBinBuiltinCall(
59145906 operation: []const u8,
59155907 info: BuiltinInfo,
59165908) !CValue {
5909 const mod = f.object.dg.module;
59175910 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
59185911
5919 const operand_ty = f.air.typeOf(bin_op.lhs);
5912 const operand_ty = f.typeOf(bin_op.lhs);
59205913 const operand_cty = try f.typeToCType(operand_ty, .complete);
59215914 const is_big = operand_cty.tag() == .array;
59225915
......@@ -5924,9 +5917,9 @@ fn airBinBuiltinCall(
59245917 const rhs = try f.resolveInst(bin_op.rhs);
59255918 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
59265919
5927 const inst_ty = f.air.typeOfIndex(inst);
5928 const inst_scalar_ty = inst_ty.scalarType();
5929 const scalar_ty = operand_ty.scalarType();
5920 const inst_ty = f.typeOfIndex(inst);
5921 const inst_scalar_ty = inst_ty.scalarType(mod);
5922 const scalar_ty = operand_ty.scalarType(mod);
59305923
59315924 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
59325925 const ref_ret = inst_scalar_cty.tag() == .array;
......@@ -5968,14 +5961,15 @@ fn airCmpBuiltinCall(
59685961 operation: enum { cmp, operator },
59695962 info: BuiltinInfo,
59705963) !CValue {
5964 const mod = f.object.dg.module;
59715965 const lhs = try f.resolveInst(data.lhs);
59725966 const rhs = try f.resolveInst(data.rhs);
59735967 try reap(f, inst, &.{ data.lhs, data.rhs });
59745968
5975 const inst_ty = f.air.typeOfIndex(inst);
5976 const inst_scalar_ty = inst_ty.scalarType();
5977 const operand_ty = f.air.typeOf(data.lhs);
5978 const scalar_ty = operand_ty.scalarType();
5969 const inst_ty = f.typeOfIndex(inst);
5970 const inst_scalar_ty = inst_ty.scalarType(mod);
5971 const operand_ty = f.typeOf(data.lhs);
5972 const scalar_ty = operand_ty.scalarType(mod);
59795973
59805974 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
59815975 const ref_ret = inst_scalar_cty.tag() == .array;
......@@ -6008,7 +6002,7 @@ fn airCmpBuiltinCall(
60086002 try writer.writeByte(')');
60096003 if (!ref_ret) try writer.print(" {s} {}", .{
60106004 compareOperatorC(operator),
6011 try f.fmtIntLiteral(Type.initTag(.i32), Value.zero),
6005 try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)),
60126006 });
60136007 try writer.writeAll(";\n");
60146008 try v.end(f, inst, writer);
......@@ -6017,28 +6011,27 @@ fn airCmpBuiltinCall(
60176011}
60186012
60196013fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue {
6014 const mod = f.object.dg.module;
60206015 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
60216016 const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
6022 const inst_ty = f.air.typeOfIndex(inst);
6017 const inst_ty = f.typeOfIndex(inst);
60236018 const ptr = try f.resolveInst(extra.ptr);
60246019 const expected_value = try f.resolveInst(extra.expected_value);
60256020 const new_value = try f.resolveInst(extra.new_value);
6026 const ptr_ty = f.air.typeOf(extra.ptr);
6027 const ty = ptr_ty.childType();
6021 const ptr_ty = f.typeOf(extra.ptr);
6022 const ty = ptr_ty.childType(mod);
60286023
60296024 const writer = f.object.writer();
60306025 const new_value_mat = try Materialize.start(f, inst, writer, ty, new_value);
60316026 try reap(f, inst, &.{ extra.ptr, extra.expected_value, extra.new_value });
60326027
6033 const target = f.object.dg.module.getTarget();
6034 var repr_pl = Type.Payload.Bits{
6035 .base = .{ .tag = .int_unsigned },
6036 .data = @intCast(u16, ty.abiSize(target) * 8),
6037 };
6038 const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty;
6028 const repr_ty = if (ty.isRuntimeFloat())
6029 mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable
6030 else
6031 ty;
60396032
60406033 const local = try f.allocLocal(inst, inst_ty);
6041 if (inst_ty.isPtrLikeOptional()) {
6034 if (inst_ty.isPtrLikeOptional(mod)) {
60426035 {
60436036 const a = try Assignment.start(f, writer, ty);
60446037 try f.writeCValue(writer, local, .Other);
......@@ -6051,7 +6044,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
60516044 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
60526045 try f.renderType(writer, ty);
60536046 try writer.writeByte(')');
6054 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
6047 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
60556048 try writer.writeAll(" *)");
60566049 try f.writeCValue(writer, ptr, .Other);
60576050 try writer.writeAll(", ");
......@@ -6093,7 +6086,7 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
60936086 try writer.print("zig_cmpxchg_{s}((zig_atomic(", .{flavor});
60946087 try f.renderType(writer, ty);
60956088 try writer.writeByte(')');
6096 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
6089 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
60976090 try writer.writeAll(" *)");
60986091 try f.writeCValue(writer, ptr, .Other);
60996092 try writer.writeAll(", ");
......@@ -6123,11 +6116,12 @@ fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue
61236116}
61246117
61256118fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
6119 const mod = f.object.dg.module;
61266120 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
61276121 const extra = f.air.extraData(Air.AtomicRmw, pl_op.payload).data;
6128 const inst_ty = f.air.typeOfIndex(inst);
6129 const ptr_ty = f.air.typeOf(pl_op.operand);
6130 const ty = ptr_ty.childType();
6122 const inst_ty = f.typeOfIndex(inst);
6123 const ptr_ty = f.typeOf(pl_op.operand);
6124 const ty = ptr_ty.childType(mod);
61316125 const ptr = try f.resolveInst(pl_op.operand);
61326126 const operand = try f.resolveInst(extra.operand);
61336127
......@@ -6135,14 +6129,10 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
61356129 const operand_mat = try Materialize.start(f, inst, writer, ty, operand);
61366130 try reap(f, inst, &.{ pl_op.operand, extra.operand });
61376131
6138 const target = f.object.dg.module.getTarget();
6139 var repr_pl = Type.Payload.Bits{
6140 .base = .{ .tag = .int_unsigned },
6141 .data = @intCast(u16, ty.abiSize(target) * 8),
6142 };
6132 const repr_bits = @intCast(u16, ty.abiSize(mod) * 8);
61436133 const is_float = ty.isRuntimeFloat();
6144 const is_128 = repr_pl.data == 128;
6145 const repr_ty = if (is_float) Type.initPayload(&repr_pl.base) else ty;
6134 const is_128 = repr_bits == 128;
6135 const repr_ty = if (is_float) mod.intType(.unsigned, repr_bits) catch unreachable else ty;
61466136
61476137 const local = try f.allocLocal(inst, inst_ty);
61486138 try writer.print("zig_atomicrmw_{s}", .{toAtomicRmwSuffix(extra.op())});
......@@ -6158,7 +6148,7 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
61586148 if (use_atomic) try writer.writeAll("zig_atomic(");
61596149 try f.renderType(writer, ty);
61606150 if (use_atomic) try writer.writeByte(')');
6161 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
6151 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
61626152 try writer.writeAll(" *)");
61636153 try f.writeCValue(writer, ptr, .Other);
61646154 try writer.writeAll(", ");
......@@ -6181,20 +6171,19 @@ fn airAtomicRmw(f: *Function, inst: Air.Inst.Index) !CValue {
61816171}
61826172
61836173fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
6174 const mod = f.object.dg.module;
61846175 const atomic_load = f.air.instructions.items(.data)[inst].atomic_load;
61856176 const ptr = try f.resolveInst(atomic_load.ptr);
61866177 try reap(f, inst, &.{atomic_load.ptr});
6187 const ptr_ty = f.air.typeOf(atomic_load.ptr);
6188 const ty = ptr_ty.childType();
6178 const ptr_ty = f.typeOf(atomic_load.ptr);
6179 const ty = ptr_ty.childType(mod);
61896180
6190 const target = f.object.dg.module.getTarget();
6191 var repr_pl = Type.Payload.Bits{
6192 .base = .{ .tag = .int_unsigned },
6193 .data = @intCast(u16, ty.abiSize(target) * 8),
6194 };
6195 const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty;
6181 const repr_ty = if (ty.isRuntimeFloat())
6182 mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable
6183 else
6184 ty;
61966185
6197 const inst_ty = f.air.typeOfIndex(inst);
6186 const inst_ty = f.typeOfIndex(inst);
61986187 const writer = f.object.writer();
61996188 const local = try f.allocLocal(inst, inst_ty);
62006189
......@@ -6203,7 +6192,7 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
62036192 try writer.writeAll(", (zig_atomic(");
62046193 try f.renderType(writer, ty);
62056194 try writer.writeByte(')');
6206 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
6195 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
62076196 try writer.writeAll(" *)");
62086197 try f.writeCValue(writer, ptr, .Other);
62096198 try writer.writeAll(", ");
......@@ -6218,9 +6207,10 @@ fn airAtomicLoad(f: *Function, inst: Air.Inst.Index) !CValue {
62186207}
62196208
62206209fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CValue {
6210 const mod = f.object.dg.module;
62216211 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
6222 const ptr_ty = f.air.typeOf(bin_op.lhs);
6223 const ty = ptr_ty.childType();
6212 const ptr_ty = f.typeOf(bin_op.lhs);
6213 const ty = ptr_ty.childType(mod);
62246214 const ptr = try f.resolveInst(bin_op.lhs);
62256215 const element = try f.resolveInst(bin_op.rhs);
62266216
......@@ -6228,17 +6218,15 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
62286218 const element_mat = try Materialize.start(f, inst, writer, ty, element);
62296219 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
62306220
6231 const target = f.object.dg.module.getTarget();
6232 var repr_pl = Type.Payload.Bits{
6233 .base = .{ .tag = .int_unsigned },
6234 .data = @intCast(u16, ty.abiSize(target) * 8),
6235 };
6236 const repr_ty = if (ty.isRuntimeFloat()) Type.initPayload(&repr_pl.base) else ty;
6221 const repr_ty = if (ty.isRuntimeFloat())
6222 mod.intType(.unsigned, @intCast(u16, ty.abiSize(mod) * 8)) catch unreachable
6223 else
6224 ty;
62376225
62386226 try writer.writeAll("zig_atomic_store((zig_atomic(");
62396227 try f.renderType(writer, ty);
62406228 try writer.writeByte(')');
6241 if (ptr_ty.isVolatilePtr()) try writer.writeAll(" volatile");
6229 if (ptr_ty.isVolatilePtr(mod)) try writer.writeAll(" volatile");
62426230 try writer.writeAll(" *)");
62436231 try f.writeCValue(writer, ptr, .Other);
62446232 try writer.writeAll(", ");
......@@ -6254,7 +6242,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa
62546242}
62556243
62566244fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void {
6257 if (ptr_ty.isSlice()) {
6245 const mod = f.object.dg.module;
6246 if (ptr_ty.isSlice(mod)) {
62586247 try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" });
62596248 } else {
62606249 try f.writeCValue(writer, ptr, .FunctionArgument);
......@@ -6262,14 +6251,14 @@ fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !vo
62626251}
62636252
62646253fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
6254 const mod = f.object.dg.module;
62656255 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
6266 const dest_ty = f.air.typeOf(bin_op.lhs);
6256 const dest_ty = f.typeOf(bin_op.lhs);
62676257 const dest_slice = try f.resolveInst(bin_op.lhs);
62686258 const value = try f.resolveInst(bin_op.rhs);
6269 const elem_ty = f.air.typeOf(bin_op.rhs);
6270 const target = f.object.dg.module.getTarget();
6271 const elem_abi_size = elem_ty.abiSize(target);
6272 const val_is_undef = if (f.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
6259 const elem_ty = f.typeOf(bin_op.rhs);
6260 const elem_abi_size = elem_ty.abiSize(mod);
6261 const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
62736262 const writer = f.object.writer();
62746263
62756264 if (val_is_undef) {
......@@ -6279,7 +6268,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
62796268 }
62806269
62816270 try writer.writeAll("memset(");
6282 switch (dest_ty.ptrSize()) {
6271 switch (dest_ty.ptrSize(mod)) {
62836272 .Slice => {
62846273 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
62856274 try writer.writeAll(", 0xaa, ");
......@@ -6291,8 +6280,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
62916280 }
62926281 },
62936282 .One => {
6294 const array_ty = dest_ty.childType();
6295 const len = array_ty.arrayLen() * elem_abi_size;
6283 const array_ty = dest_ty.childType(mod);
6284 const len = array_ty.arrayLen(mod) * elem_abi_size;
62966285
62976286 try f.writeCValue(writer, dest_slice, .FunctionArgument);
62986287 try writer.print(", 0xaa, {d});\n", .{len});
......@@ -6303,32 +6292,33 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
63036292 return .none;
63046293 }
63056294
6306 if (elem_abi_size > 1 or dest_ty.isVolatilePtr()) {
6295 if (elem_abi_size > 1 or dest_ty.isVolatilePtr(mod)) {
63076296 // For the assignment in this loop, the array pointer needs to get
63086297 // casted to a regular pointer, otherwise an error like this occurs:
63096298 // error: array type 'uint32_t[20]' (aka 'unsigned int[20]') is not assignable
6310 var elem_ptr_ty_pl: Type.Payload.ElemType = .{
6311 .base = .{ .tag = .c_mut_pointer },
6312 .data = elem_ty,
6313 };
6314 const elem_ptr_ty = Type.initPayload(&elem_ptr_ty_pl.base);
6299 const elem_ptr_ty = try mod.ptrType(.{
6300 .child = elem_ty.ip_index,
6301 .flags = .{
6302 .size = .C,
6303 },
6304 });
63156305
63166306 const index = try f.allocLocal(inst, Type.usize);
63176307
63186308 try writer.writeAll("for (");
63196309 try f.writeCValue(writer, index, .Other);
63206310 try writer.writeAll(" = ");
6321 try f.object.dg.renderValue(writer, Type.usize, Value.zero, .Initializer);
6311 try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, 0), .Initializer);
63226312 try writer.writeAll("; ");
63236313 try f.writeCValue(writer, index, .Other);
63246314 try writer.writeAll(" != ");
6325 switch (dest_ty.ptrSize()) {
6315 switch (dest_ty.ptrSize(mod)) {
63266316 .Slice => {
63276317 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "len" });
63286318 },
63296319 .One => {
6330 const array_ty = dest_ty.childType();
6331 try writer.print("{d}", .{array_ty.arrayLen()});
6320 const array_ty = dest_ty.childType(mod);
6321 try writer.print("{d}", .{array_ty.arrayLen(mod)});
63326322 },
63336323 .Many, .C => unreachable,
63346324 }
......@@ -6357,7 +6347,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
63576347 const bitcasted = try bitcast(f, Type.u8, value, elem_ty);
63586348
63596349 try writer.writeAll("memset(");
6360 switch (dest_ty.ptrSize()) {
6350 switch (dest_ty.ptrSize(mod)) {
63616351 .Slice => {
63626352 try f.writeCValueMember(writer, dest_slice, .{ .identifier = "ptr" });
63636353 try writer.writeAll(", ");
......@@ -6367,8 +6357,8 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
63676357 try writer.writeAll(");\n");
63686358 },
63696359 .One => {
6370 const array_ty = dest_ty.childType();
6371 const len = array_ty.arrayLen() * elem_abi_size;
6360 const array_ty = dest_ty.childType(mod);
6361 const len = array_ty.arrayLen(mod) * elem_abi_size;
63726362
63736363 try f.writeCValue(writer, dest_slice, .FunctionArgument);
63746364 try writer.writeAll(", ");
......@@ -6383,12 +6373,12 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
63836373}
63846374
63856375fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
6376 const mod = f.object.dg.module;
63866377 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
63876378 const dest_ptr = try f.resolveInst(bin_op.lhs);
63886379 const src_ptr = try f.resolveInst(bin_op.rhs);
6389 const dest_ty = f.air.typeOf(bin_op.lhs);
6390 const src_ty = f.air.typeOf(bin_op.rhs);
6391 const target = f.object.dg.module.getTarget();
6380 const dest_ty = f.typeOf(bin_op.lhs);
6381 const src_ty = f.typeOf(bin_op.rhs);
63926382 const writer = f.object.writer();
63936383
63946384 try writer.writeAll("memcpy(");
......@@ -6396,10 +6386,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
63966386 try writer.writeAll(", ");
63976387 try writeSliceOrPtr(f, writer, src_ptr, src_ty);
63986388 try writer.writeAll(", ");
6399 switch (dest_ty.ptrSize()) {
6389 switch (dest_ty.ptrSize(mod)) {
64006390 .Slice => {
6401 const elem_ty = dest_ty.childType();
6402 const elem_abi_size = elem_ty.abiSize(target);
6391 const elem_ty = dest_ty.childType(mod);
6392 const elem_abi_size = elem_ty.abiSize(mod);
64036393 try f.writeCValueMember(writer, dest_ptr, .{ .identifier = "len" });
64046394 if (elem_abi_size > 1) {
64056395 try writer.print(" * {d});\n", .{elem_abi_size});
......@@ -6408,10 +6398,10 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
64086398 }
64096399 },
64106400 .One => {
6411 const array_ty = dest_ty.childType();
6412 const elem_ty = array_ty.childType();
6413 const elem_abi_size = elem_ty.abiSize(target);
6414 const len = array_ty.arrayLen() * elem_abi_size;
6401 const array_ty = dest_ty.childType(mod);
6402 const elem_ty = array_ty.childType(mod);
6403 const elem_abi_size = elem_ty.abiSize(mod);
6404 const len = array_ty.arrayLen(mod) * elem_abi_size;
64156405 try writer.print("{d});\n", .{len});
64166406 },
64176407 .Many, .C => unreachable,
......@@ -6422,16 +6412,16 @@ fn airMemcpy(f: *Function, inst: Air.Inst.Index) !CValue {
64226412}
64236413
64246414fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6415 const mod = f.object.dg.module;
64256416 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
64266417 const union_ptr = try f.resolveInst(bin_op.lhs);
64276418 const new_tag = try f.resolveInst(bin_op.rhs);
64286419 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
64296420
6430 const target = f.object.dg.module.getTarget();
6431 const union_ty = f.air.typeOf(bin_op.lhs).childType();
6432 const layout = union_ty.unionGetLayout(target);
6421 const union_ty = f.typeOf(bin_op.lhs).childType(mod);
6422 const layout = union_ty.unionGetLayout(mod);
64336423 if (layout.tag_size == 0) return .none;
6434 const tag_ty = union_ty.unionTagTypeSafety().?;
6424 const tag_ty = union_ty.unionTagTypeSafety(mod).?;
64356425
64366426 const writer = f.object.writer();
64376427 const a = try Assignment.start(f, writer, tag_ty);
......@@ -6443,17 +6433,17 @@ fn airSetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
64436433}
64446434
64456435fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
6436 const mod = f.object.dg.module;
64466437 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
64476438
64486439 const operand = try f.resolveInst(ty_op.operand);
64496440 try reap(f, inst, &.{ty_op.operand});
64506441
6451 const union_ty = f.air.typeOf(ty_op.operand);
6452 const target = f.object.dg.module.getTarget();
6453 const layout = union_ty.unionGetLayout(target);
6442 const union_ty = f.typeOf(ty_op.operand);
6443 const layout = union_ty.unionGetLayout(mod);
64546444 if (layout.tag_size == 0) return .none;
64556445
6456 const inst_ty = f.air.typeOfIndex(inst);
6446 const inst_ty = f.typeOfIndex(inst);
64576447 const writer = f.object.writer();
64586448 const local = try f.allocLocal(inst, inst_ty);
64596449 const a = try Assignment.start(f, writer, inst_ty);
......@@ -6465,10 +6455,11 @@ fn airGetUnionTag(f: *Function, inst: Air.Inst.Index) !CValue {
64656455}
64666456
64676457fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
6458 const mod = f.object.dg.module;
64686459 const un_op = f.air.instructions.items(.data)[inst].un_op;
64696460
6470 const inst_ty = f.air.typeOfIndex(inst);
6471 const enum_ty = f.air.typeOf(un_op);
6461 const inst_ty = f.typeOfIndex(inst);
6462 const enum_ty = f.typeOf(un_op);
64726463 const operand = try f.resolveInst(un_op);
64736464 try reap(f, inst, &.{un_op});
64746465
......@@ -6476,7 +6467,7 @@ fn airTagName(f: *Function, inst: Air.Inst.Index) !CValue {
64766467 const local = try f.allocLocal(inst, inst_ty);
64776468 try f.writeCValue(writer, local, .Other);
64786469 try writer.print(" = {s}(", .{
6479 try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl() }, .{ .tag_name = enum_ty }),
6470 try f.getLazyFnName(.{ .tag_name = enum_ty.getOwnerDecl(mod) }, .{ .tag_name = enum_ty }),
64806471 });
64816472 try f.writeCValue(writer, operand, .Other);
64826473 try writer.writeAll(");\n");
......@@ -6488,7 +6479,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
64886479 const un_op = f.air.instructions.items(.data)[inst].un_op;
64896480
64906481 const writer = f.object.writer();
6491 const inst_ty = f.air.typeOfIndex(inst);
6482 const inst_ty = f.typeOfIndex(inst);
64926483 const operand = try f.resolveInst(un_op);
64936484 try reap(f, inst, &.{un_op});
64946485 const local = try f.allocLocal(inst, inst_ty);
......@@ -6501,13 +6492,14 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
65016492}
65026493
65036494fn airSplat(f: *Function, inst: Air.Inst.Index) !CValue {
6495 const mod = f.object.dg.module;
65046496 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
65056497
65066498 const operand = try f.resolveInst(ty_op.operand);
65076499 try reap(f, inst, &.{ty_op.operand});
65086500
6509 const inst_ty = f.air.typeOfIndex(inst);
6510 const inst_scalar_ty = inst_ty.scalarType();
6501 const inst_ty = f.typeOfIndex(inst);
6502 const inst_scalar_ty = inst_ty.scalarType(mod);
65116503
65126504 const writer = f.object.writer();
65136505 const local = try f.allocLocal(inst, inst_ty);
......@@ -6532,7 +6524,7 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
65326524 const rhs = try f.resolveInst(extra.rhs);
65336525 try reap(f, inst, &.{ pl_op.operand, extra.lhs, extra.rhs });
65346526
6535 const inst_ty = f.air.typeOfIndex(inst);
6527 const inst_ty = f.typeOfIndex(inst);
65366528
65376529 const writer = f.object.writer();
65386530 const local = try f.allocLocal(inst, inst_ty);
......@@ -6555,41 +6547,31 @@ fn airSelect(f: *Function, inst: Air.Inst.Index) !CValue {
65556547}
65566548
65576549fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
6550 const mod = f.object.dg.module;
65586551 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
65596552 const extra = f.air.extraData(Air.Shuffle, ty_pl.payload).data;
65606553
6561 const mask = f.air.values[extra.mask];
6554 const mask = extra.mask.toValue();
65626555 const lhs = try f.resolveInst(extra.a);
65636556 const rhs = try f.resolveInst(extra.b);
65646557
6565 const module = f.object.dg.module;
6566 const target = module.getTarget();
6567 const inst_ty = f.air.typeOfIndex(inst);
6558 const inst_ty = f.typeOfIndex(inst);
65686559
65696560 const writer = f.object.writer();
65706561 const local = try f.allocLocal(inst, inst_ty);
65716562 try reap(f, inst, &.{ extra.a, extra.b }); // local cannot alias operands
65726563 for (0..extra.mask_len) |index| {
6573 var dst_pl = Value.Payload.U64{
6574 .base = .{ .tag = .int_u64 },
6575 .data = @intCast(u64, index),
6576 };
6577
65786564 try f.writeCValue(writer, local, .Other);
65796565 try writer.writeByte('[');
6580 try f.object.dg.renderValue(writer, Type.usize, Value.initPayload(&dst_pl.base), .Other);
6566 try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, index), .Other);
65816567 try writer.writeAll("] = ");
65826568
6583 var buf: Value.ElemValueBuffer = undefined;
6584 const mask_elem = mask.elemValueBuffer(module, index, &buf).toSignedInt(target);
6585 var src_pl = Value.Payload.U64{
6586 .base = .{ .tag = .int_u64 },
6587 .data = @intCast(u64, mask_elem ^ mask_elem >> 63),
6588 };
6569 const mask_elem = (try mask.elemValue(mod, index)).toSignedInt(mod);
6570 const src_val = try mod.intValue(Type.usize, @intCast(u64, mask_elem ^ mask_elem >> 63));
65896571
65906572 try f.writeCValue(writer, if (mask_elem >= 0) lhs else rhs, .Other);
65916573 try writer.writeByte('[');
6592 try f.object.dg.renderValue(writer, Type.usize, Value.initPayload(&src_pl.base), .Other);
6574 try f.object.dg.renderValue(writer, Type.usize, src_val, .Other);
65936575 try writer.writeAll("];\n");
65946576 }
65956577
......@@ -6597,16 +6579,16 @@ fn airShuffle(f: *Function, inst: Air.Inst.Index) !CValue {
65976579}
65986580
65996581fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
6582 const mod = f.object.dg.module;
66006583 const reduce = f.air.instructions.items(.data)[inst].reduce;
66016584
6602 const target = f.object.dg.module.getTarget();
6603 const scalar_ty = f.air.typeOfIndex(inst);
6585 const scalar_ty = f.typeOfIndex(inst);
66046586 const operand = try f.resolveInst(reduce.operand);
66056587 try reap(f, inst, &.{reduce.operand});
6606 const operand_ty = f.air.typeOf(reduce.operand);
6588 const operand_ty = f.typeOf(reduce.operand);
66076589 const writer = f.object.writer();
66086590
6609 const use_operator = scalar_ty.bitSize(target) <= 64;
6591 const use_operator = scalar_ty.bitSize(mod) <= 64;
66106592 const op: union(enum) {
66116593 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
66126594 float_op: Func,
......@@ -6617,28 +6599,28 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66176599 .And => if (use_operator) .{ .infix = " &= " } else .{ .builtin = .{ .operation = "and" } },
66186600 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },
66196601 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },
6620 .Min => switch (scalar_ty.zigTypeTag()) {
6602 .Min => switch (scalar_ty.zigTypeTag(mod)) {
66216603 .Int => if (use_operator) .{ .ternary = " < " } else .{
66226604 .builtin = .{ .operation = "min" },
66236605 },
66246606 .Float => .{ .float_op = .{ .operation = "fmin" } },
66256607 else => unreachable,
66266608 },
6627 .Max => switch (scalar_ty.zigTypeTag()) {
6609 .Max => switch (scalar_ty.zigTypeTag(mod)) {
66286610 .Int => if (use_operator) .{ .ternary = " > " } else .{
66296611 .builtin = .{ .operation = "max" },
66306612 },
66316613 .Float => .{ .float_op = .{ .operation = "fmax" } },
66326614 else => unreachable,
66336615 },
6634 .Add => switch (scalar_ty.zigTypeTag()) {
6616 .Add => switch (scalar_ty.zigTypeTag(mod)) {
66356617 .Int => if (use_operator) .{ .infix = " += " } else .{
66366618 .builtin = .{ .operation = "addw", .info = .bits },
66376619 },
66386620 .Float => .{ .builtin = .{ .operation = "add" } },
66396621 else => unreachable,
66406622 },
6641 .Mul => switch (scalar_ty.zigTypeTag()) {
6623 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
66426624 .Int => if (use_operator) .{ .infix = " *= " } else .{
66436625 .builtin = .{ .operation = "mulw", .info = .bits },
66446626 },
......@@ -6663,43 +6645,42 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
66636645 try f.writeCValue(writer, accum, .Other);
66646646 try writer.writeAll(" = ");
66656647
6666 var arena = std.heap.ArenaAllocator.init(f.object.dg.gpa);
6667 defer arena.deinit();
6668
6669 const ExpectedContents = union {
6670 u: Value.Payload.U64,
6671 i: Value.Payload.I64,
6672 f16: Value.Payload.Float_16,
6673 f32: Value.Payload.Float_32,
6674 f64: Value.Payload.Float_64,
6675 f80: Value.Payload.Float_80,
6676 f128: Value.Payload.Float_128,
6677 };
6678 var stack align(@alignOf(ExpectedContents)) =
6679 std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
6680
66816648 try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
6682 .Or, .Xor, .Add => Value.zero,
6683 .And => switch (scalar_ty.zigTypeTag()) {
6684 .Bool => Value.one,
6685 else => switch (scalar_ty.intInfo(target).signedness) {
6686 .unsigned => try scalar_ty.maxInt(stack.get(), target),
6687 .signed => Value.negative_one,
6649 .Or, .Xor => switch (scalar_ty.zigTypeTag(mod)) {
6650 .Bool => Value.false,
6651 .Int => try mod.intValue(scalar_ty, 0),
6652 else => unreachable,
6653 },
6654 .And => switch (scalar_ty.zigTypeTag(mod)) {
6655 .Bool => Value.true,
6656 .Int => switch (scalar_ty.intInfo(mod).signedness) {
6657 .unsigned => try scalar_ty.maxIntScalar(mod, scalar_ty),
6658 .signed => try mod.intValue(scalar_ty, -1),
66886659 },
6660 else => unreachable,
6661 },
6662 .Add => switch (scalar_ty.zigTypeTag(mod)) {
6663 .Int => try mod.intValue(scalar_ty, 0),
6664 .Float => try mod.floatValue(scalar_ty, 0.0),
6665 else => unreachable,
66896666 },
6690 .Min => switch (scalar_ty.zigTypeTag()) {
6691 .Bool => Value.one,
6692 .Int => try scalar_ty.maxInt(stack.get(), target),
6693 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
6667 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
6668 .Int => try mod.intValue(scalar_ty, 1),
6669 .Float => try mod.floatValue(scalar_ty, 1.0),
66946670 else => unreachable,
66956671 },
6696 .Max => switch (scalar_ty.zigTypeTag()) {
6697 .Bool => Value.zero,
6698 .Int => try scalar_ty.minInt(stack.get(), target),
6699 .Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
6672 .Min => switch (scalar_ty.zigTypeTag(mod)) {
6673 .Bool => Value.true,
6674 .Int => try scalar_ty.maxIntScalar(mod, scalar_ty),
6675 .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
6676 else => unreachable,
6677 },
6678 .Max => switch (scalar_ty.zigTypeTag(mod)) {
6679 .Bool => Value.false,
6680 .Int => try scalar_ty.minIntScalar(mod, scalar_ty),
6681 .Float => try mod.floatValue(scalar_ty, std.math.nan_f128),
67006682 else => unreachable,
67016683 },
6702 .Mul => Value.one,
67036684 }, .Initializer);
67046685 try writer.writeAll(";\n");
67056686
......@@ -6753,9 +6734,11 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
67536734}
67546735
67556736fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
6737 const mod = f.object.dg.module;
6738 const ip = &mod.intern_pool;
67566739 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
6757 const inst_ty = f.air.typeOfIndex(inst);
6758 const len = @intCast(usize, inst_ty.arrayLen());
6740 const inst_ty = f.typeOfIndex(inst);
6741 const len = @intCast(usize, inst_ty.arrayLen(mod));
67596742 const elements = @ptrCast([]const Air.Inst.Ref, f.air.extra[ty_pl.payload..][0..len]);
67606743 const gpa = f.object.dg.gpa;
67616744 const resolved_elements = try gpa.alloc(CValue, elements.len);
......@@ -6770,13 +6753,11 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67706753 }
67716754 }
67726755
6773 const target = f.object.dg.module.getTarget();
6774
67756756 const writer = f.object.writer();
67766757 const local = try f.allocLocal(inst, inst_ty);
6777 switch (inst_ty.zigTypeTag()) {
6758 switch (inst_ty.zigTypeTag(mod)) {
67786759 .Array, .Vector => {
6779 const elem_ty = inst_ty.childType();
6760 const elem_ty = inst_ty.childType(mod);
67806761 const a = try Assignment.init(f, elem_ty);
67816762 for (resolved_elements, 0..) |element, i| {
67826763 try a.restart(f, writer);
......@@ -6786,7 +6767,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67866767 try f.writeCValue(writer, element, .Other);
67876768 try a.end(f, writer);
67886769 }
6789 if (inst_ty.sentinel()) |sentinel| {
6770 if (inst_ty.sentinel(mod)) |sentinel| {
67906771 try a.restart(f, writer);
67916772 try f.writeCValue(writer, local, .Other);
67926773 try writer.print("[{d}]", .{resolved_elements.len});
......@@ -6795,17 +6776,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
67956776 try a.end(f, writer);
67966777 }
67976778 },
6798 .Struct => switch (inst_ty.containerLayout()) {
6779 .Struct => switch (inst_ty.containerLayout(mod)) {
67996780 .Auto, .Extern => for (resolved_elements, 0..) |element, field_i| {
6800 if (inst_ty.structFieldIsComptime(field_i)) continue;
6801 const field_ty = inst_ty.structFieldType(field_i);
6802 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
6781 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6782 const field_ty = inst_ty.structFieldType(field_i, mod);
6783 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68036784
68046785 const a = try Assignment.start(f, writer, field_ty);
6805 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple())
6786 try f.writeCValueMember(writer, local, if (inst_ty.isSimpleTuple(mod))
68066787 .{ .field = field_i }
68076788 else
6808 .{ .identifier = inst_ty.structFieldName(field_i) });
6789 .{ .identifier = ip.stringToSlice(inst_ty.structFieldName(field_i, mod)) });
68096790 try a.assign(f, writer);
68106791 try f.writeCValue(writer, element, .Other);
68116792 try a.end(f, writer);
......@@ -6813,22 +6794,17 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68136794 .Packed => {
68146795 try f.writeCValue(writer, local, .Other);
68156796 try writer.writeAll(" = ");
6816 const int_info = inst_ty.intInfo(target);
6797 const int_info = inst_ty.intInfo(mod);
68176798
6818 var bit_offset_ty_pl = Type.Payload.Bits{
6819 .base = .{ .tag = .int_unsigned },
6820 .data = Type.smallestUnsignedBits(int_info.bits - 1),
6821 };
6822 const bit_offset_ty = Type.initPayload(&bit_offset_ty_pl.base);
6799 const bit_offset_ty = try mod.intType(.unsigned, Type.smallestUnsignedBits(int_info.bits - 1));
68236800
6824 var bit_offset_val_pl: Value.Payload.U64 = .{ .base = .{ .tag = .int_u64 }, .data = 0 };
6825 const bit_offset_val = Value.initPayload(&bit_offset_val_pl.base);
6801 var bit_offset: u64 = 0;
68266802
68276803 var empty = true;
68286804 for (0..elements.len) |field_i| {
6829 if (inst_ty.structFieldIsComptime(field_i)) continue;
6830 const field_ty = inst_ty.structFieldType(field_i);
6831 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
6805 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6806 const field_ty = inst_ty.structFieldType(field_i, mod);
6807 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68326808
68336809 if (!empty) {
68346810 try writer.writeAll("zig_or_");
......@@ -6839,9 +6815,9 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68396815 }
68406816 empty = true;
68416817 for (resolved_elements, 0..) |element, field_i| {
6842 if (inst_ty.structFieldIsComptime(field_i)) continue;
6843 const field_ty = inst_ty.structFieldType(field_i);
6844 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
6818 if (inst_ty.structFieldIsComptime(field_i, mod)) continue;
6819 const field_ty = inst_ty.structFieldType(field_i, mod);
6820 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
68456821
68466822 if (!empty) try writer.writeAll(", ");
68476823 // TODO: Skip this entire shift if val is 0?
......@@ -6849,13 +6825,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68496825 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_ty);
68506826 try writer.writeByte('(');
68516827
6852 if (inst_ty.isAbiInt() and (field_ty.isAbiInt() or field_ty.isPtrAtRuntime())) {
6828 if (inst_ty.isAbiInt(mod) and (field_ty.isAbiInt(mod) or field_ty.isPtrAtRuntime(mod))) {
68536829 try f.renderIntCast(writer, inst_ty, element, .{}, field_ty, .FunctionArgument);
68546830 } else {
68556831 try writer.writeByte('(');
68566832 try f.renderType(writer, inst_ty);
68576833 try writer.writeByte(')');
6858 if (field_ty.isPtrAtRuntime()) {
6834 if (field_ty.isPtrAtRuntime(mod)) {
68596835 try writer.writeByte('(');
68606836 try f.renderType(writer, switch (int_info.signedness) {
68616837 .unsigned => Type.usize,
......@@ -6867,12 +6843,13 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68676843 }
68686844
68696845 try writer.writeAll(", ");
6846 const bit_offset_val = try mod.intValue(bit_offset_ty, bit_offset);
68706847 try f.object.dg.renderValue(writer, bit_offset_ty, bit_offset_val, .FunctionArgument);
68716848 try f.object.dg.renderBuiltinInfo(writer, inst_ty, .bits);
68726849 try writer.writeByte(')');
68736850 if (!empty) try writer.writeByte(')');
68746851
6875 bit_offset_val_pl.data += field_ty.bitSize(target);
6852 bit_offset += field_ty.bitSize(mod);
68766853 empty = false;
68776854 }
68786855
......@@ -6886,14 +6863,15 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue {
68866863}
68876864
68886865fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
6866 const mod = f.object.dg.module;
6867 const ip = &mod.intern_pool;
68896868 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
68906869 const extra = f.air.extraData(Air.UnionInit, ty_pl.payload).data;
68916870
6892 const union_ty = f.air.typeOfIndex(inst);
6893 const target = f.object.dg.module.getTarget();
6894 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
6871 const union_ty = f.typeOfIndex(inst);
6872 const union_obj = mod.typeToUnion(union_ty).?;
68956873 const field_name = union_obj.fields.keys()[extra.field_index];
6896 const payload_ty = f.air.typeOf(extra.init);
6874 const payload_ty = f.typeOf(extra.init);
68976875 const payload = try f.resolveInst(extra.init);
68986876 try reap(f, inst, &.{extra.init});
68996877
......@@ -6907,19 +6885,14 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
69076885 return local;
69086886 }
69096887
6910 const field: CValue = if (union_ty.unionTagTypeSafety()) |tag_ty| field: {
6911 const layout = union_ty.unionGetLayout(target);
6888 const field: CValue = if (union_ty.unionTagTypeSafety(mod)) |tag_ty| field: {
6889 const layout = union_ty.unionGetLayout(mod);
69126890 if (layout.tag_size != 0) {
6913 const field_index = tag_ty.enumFieldIndex(field_name).?;
6891 const field_index = tag_ty.enumFieldIndex(field_name, mod).?;
69146892
6915 var tag_pl: Value.Payload.U32 = .{
6916 .base = .{ .tag = .enum_field_index },
6917 .data = @intCast(u32, field_index),
6918 };
6919 const tag_val = Value.initPayload(&tag_pl.base);
6893 const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index);
69206894
6921 var int_pl: Value.Payload.U64 = undefined;
6922 const int_val = tag_val.enumToInt(tag_ty, &int_pl);
6895 const int_val = try tag_val.enumToInt(tag_ty, mod);
69236896
69246897 const a = try Assignment.start(f, writer, tag_ty);
69256898 try f.writeCValueMember(writer, local, .{ .identifier = "tag" });
......@@ -6927,8 +6900,8 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue {
69276900 try writer.print("{}", .{try f.fmtIntLiteral(tag_ty, int_val)});
69286901 try a.end(f, writer);
69296902 }
6930 break :field .{ .payload_identifier = field_name };
6931 } else .{ .identifier = field_name };
6903 break :field .{ .payload_identifier = ip.stringToSlice(field_name) };
6904 } else .{ .identifier = ip.stringToSlice(field_name) };
69326905
69336906 const a = try Assignment.start(f, writer, payload_ty);
69346907 try f.writeCValueMember(writer, local, field);
......@@ -6963,7 +6936,7 @@ fn airWasmMemorySize(f: *Function, inst: Air.Inst.Index) !CValue {
69636936 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
69646937
69656938 const writer = f.object.writer();
6966 const inst_ty = f.air.typeOfIndex(inst);
6939 const inst_ty = f.typeOfIndex(inst);
69676940 const local = try f.allocLocal(inst, inst_ty);
69686941 try f.writeCValue(writer, local, .Other);
69696942
......@@ -6977,7 +6950,7 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
69776950 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
69786951
69796952 const writer = f.object.writer();
6980 const inst_ty = f.air.typeOfIndex(inst);
6953 const inst_ty = f.typeOfIndex(inst);
69816954 const operand = try f.resolveInst(pl_op.operand);
69826955 try reap(f, inst, &.{pl_op.operand});
69836956 const local = try f.allocLocal(inst, inst_ty);
......@@ -6991,13 +6964,14 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
69916964}
69926965
69936966fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
6967 const mod = f.object.dg.module;
69946968 const un_op = f.air.instructions.items(.data)[inst].un_op;
69956969
69966970 const operand = try f.resolveInst(un_op);
69976971 try reap(f, inst, &.{un_op});
69986972
6999 const operand_ty = f.air.typeOf(un_op);
7000 const scalar_ty = operand_ty.scalarType();
6973 const operand_ty = f.typeOf(un_op);
6974 const scalar_ty = operand_ty.scalarType(mod);
70016975
70026976 const writer = f.object.writer();
70036977 const local = try f.allocLocal(inst, operand_ty);
......@@ -7016,13 +6990,14 @@ fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
70166990}
70176991
70186992fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
6993 const mod = f.object.dg.module;
70196994 const un_op = f.air.instructions.items(.data)[inst].un_op;
70206995
70216996 const operand = try f.resolveInst(un_op);
70226997 try reap(f, inst, &.{un_op});
70236998
7024 const inst_ty = f.air.typeOfIndex(inst);
7025 const inst_scalar_ty = inst_ty.scalarType();
6999 const inst_ty = f.typeOfIndex(inst);
7000 const inst_scalar_ty = inst_ty.scalarType(mod);
70267001
70277002 const writer = f.object.writer();
70287003 const local = try f.allocLocal(inst, inst_ty);
......@@ -7043,14 +7018,15 @@ fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVal
70437018}
70447019
70457020fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
7021 const mod = f.object.dg.module;
70467022 const bin_op = f.air.instructions.items(.data)[inst].bin_op;
70477023
70487024 const lhs = try f.resolveInst(bin_op.lhs);
70497025 const rhs = try f.resolveInst(bin_op.rhs);
70507026 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
70517027
7052 const inst_ty = f.air.typeOfIndex(inst);
7053 const inst_scalar_ty = inst_ty.scalarType();
7028 const inst_ty = f.typeOfIndex(inst);
7029 const inst_scalar_ty = inst_ty.scalarType(mod);
70547030
70557031 const writer = f.object.writer();
70567032 const local = try f.allocLocal(inst, inst_ty);
......@@ -7074,6 +7050,7 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa
70747050}
70757051
70767052fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7053 const mod = f.object.dg.module;
70777054 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
70787055 const bin_op = f.air.extraData(Air.Bin, pl_op.payload).data;
70797056
......@@ -7082,8 +7059,8 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
70827059 const addend = try f.resolveInst(pl_op.operand);
70837060 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs, pl_op.operand });
70847061
7085 const inst_ty = f.air.typeOfIndex(inst);
7086 const inst_scalar_ty = inst_ty.scalarType();
7062 const inst_ty = f.typeOfIndex(inst);
7063 const inst_scalar_ty = inst_ty.scalarType(mod);
70877064
70887065 const writer = f.object.writer();
70897066 const local = try f.allocLocal(inst, inst_ty);
......@@ -7108,7 +7085,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
71087085}
71097086
71107087fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
7111 const inst_ty = f.air.typeOfIndex(inst);
7088 const inst_ty = f.typeOfIndex(inst);
71127089 const fn_cty = try f.typeToCType(f.object.dg.decl.?.ty, .complete);
71137090 const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
71147091
......@@ -7127,7 +7104,7 @@ fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
71277104fn airCVaArg(f: *Function, inst: Air.Inst.Index) !CValue {
71287105 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
71297106
7130 const inst_ty = f.air.typeOfIndex(inst);
7107 const inst_ty = f.typeOfIndex(inst);
71317108 const va_list = try f.resolveInst(ty_op.operand);
71327109 try reap(f, inst, &.{ty_op.operand});
71337110
......@@ -7158,7 +7135,7 @@ fn airCVaEnd(f: *Function, inst: Air.Inst.Index) !CValue {
71587135fn airCVaCopy(f: *Function, inst: Air.Inst.Index) !CValue {
71597136 const ty_op = f.air.instructions.items(.data)[inst].ty_op;
71607137
7161 const inst_ty = f.air.typeOfIndex(inst);
7138 const inst_ty = f.typeOfIndex(inst);
71627139 const va_list = try f.resolveInst(ty_op.operand);
71637140 try reap(f, inst, &.{ty_op.operand});
71647141
......@@ -7279,8 +7256,9 @@ fn signAbbrev(signedness: std.builtin.Signedness) u8 {
72797256 };
72807257}
72817258
7282fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 {
7283 return if (ty.isInt()) switch (ty.intInfo(target).bits) {
7259fn compilerRtAbbrev(ty: Type, mod: *Module) []const u8 {
7260 const target = mod.getTarget();
7261 return if (ty.isInt(mod)) switch (ty.intInfo(mod).bits) {
72847262 1...32 => "si",
72857263 33...64 => "di",
72867264 65...128 => "ti",
......@@ -7407,7 +7385,7 @@ fn undefPattern(comptime IntType: type) IntType {
74077385
74087386const FormatIntLiteralContext = struct {
74097387 dg: *DeclGen,
7410 int_info: std.builtin.Type.Int,
7388 int_info: InternPool.Key.IntType,
74117389 kind: CType.Kind,
74127390 cty: CType,
74137391 val: Value,
......@@ -7418,7 +7396,8 @@ fn formatIntLiteral(
74187396 options: std.fmt.FormatOptions,
74197397 writer: anytype,
74207398) @TypeOf(writer).Error!void {
7421 const target = data.dg.module.getTarget();
7399 const mod = data.dg.module;
7400 const target = mod.getTarget();
74227401
74237402 const ExpectedContents = struct {
74247403 const base = 10;
......@@ -7438,7 +7417,7 @@ fn formatIntLiteral(
74387417 defer allocator.free(undef_limbs);
74397418
74407419 var int_buf: Value.BigIntSpace = undefined;
7441 const int = if (data.val.isUndefDeep()) blk: {
7420 const int = if (data.val.isUndefDeep(mod)) blk: {
74427421 undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits));
74437422 @memset(undef_limbs, undefPattern(BigIntLimb));
74447423
......@@ -7449,7 +7428,7 @@ fn formatIntLiteral(
74497428 };
74507429 undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits);
74517430 break :blk undef_int.toConst();
7452 } else data.val.toBigInt(&int_buf, target);
7431 } else data.val.toBigInt(&int_buf, mod);
74537432 assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits));
74547433
74557434 const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8);
......@@ -7576,10 +7555,6 @@ fn formatIntLiteral(
75767555 c_limb_int_info.signedness = .unsigned;
75777556 c_limb_cty = c_limb_info.cty;
75787557 }
7579 var c_limb_val_pl = Value.Payload.BigInt{
7580 .base = .{ .tag = if (c_limb_mut.positive) .int_big_positive else .int_big_negative },
7581 .data = c_limb_mut.limbs[0..c_limb_mut.len],
7582 };
75837558
75847559 if (limb_offset > 0) try writer.writeAll(", ");
75857560 try formatIntLiteral(.{
......@@ -7587,7 +7562,7 @@ fn formatIntLiteral(
75877562 .int_info = c_limb_int_info,
75887563 .kind = data.kind,
75897564 .cty = c_limb_cty,
7590 .val = Value.initPayload(&c_limb_val_pl.base),
7565 .val = try mod.intValue_big(Type.comptime_int, c_limb_mut.toConst()),
75917566 }, fmt, options, writer);
75927567 }
75937568 }
......@@ -7684,20 +7659,21 @@ const Vectorize = struct {
76847659 index: CValue = .none,
76857660
76867661 pub fn start(f: *Function, inst: Air.Inst.Index, writer: anytype, ty: Type) !Vectorize {
7687 return if (ty.zigTypeTag() == .Vector) index: {
7688 var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = ty.vectorLen() };
7662 const mod = f.object.dg.module;
7663 return if (ty.zigTypeTag(mod) == .Vector) index: {
7664 const len_val = try mod.intValue(Type.usize, ty.vectorLen(mod));
76897665
76907666 const local = try f.allocLocal(inst, Type.usize);
76917667
76927668 try writer.writeAll("for (");
76937669 try f.writeCValue(writer, local, .Other);
7694 try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
7670 try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))});
76957671 try f.writeCValue(writer, local, .Other);
76967672 try writer.print(" < {d}; ", .{
7697 try f.fmtIntLiteral(Type.usize, Value.initPayload(&len_pl.base)),
7673 try f.fmtIntLiteral(Type.usize, len_val),
76987674 });
76997675 try f.writeCValue(writer, local, .Other);
7700 try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, Value.one)});
7676 try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
77017677 f.object.indent_writer.pushIndent();
77027678
77037679 break :index .{ .index = local };
......@@ -7721,34 +7697,30 @@ const Vectorize = struct {
77217697 }
77227698};
77237699
7724const LowerFnRetTyBuffer = struct {
7725 names: [1][]const u8,
7726 types: [1]Type,
7727 values: [1]Value,
7728 payload: Type.Payload.AnonStruct,
7729};
7730fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, target: std.Target) Type {
7731 if (ret_ty.zigTypeTag() == .NoReturn) return Type.initTag(.noreturn);
7732
7733 if (lowersToArray(ret_ty, target)) {
7734 buffer.names = [1][]const u8{"array"};
7735 buffer.types = [1]Type{ret_ty};
7736 buffer.values = [1]Value{Value.initTag(.unreachable_value)};
7737 buffer.payload = .{ .data = .{
7738 .names = &buffer.names,
7739 .types = &buffer.types,
7740 .values = &buffer.values,
7741 } };
7742 return Type.initPayload(&buffer.payload.base);
7700fn lowerFnRetTy(ret_ty: Type, mod: *Module) !Type {
7701 if (ret_ty.ip_index == .noreturn_type) return Type.noreturn;
7702
7703 if (lowersToArray(ret_ty, mod)) {
7704 const names = [1]InternPool.NullTerminatedString{
7705 try mod.intern_pool.getOrPutString(mod.gpa, "array"),
7706 };
7707 const types = [1]InternPool.Index{ret_ty.ip_index};
7708 const values = [1]InternPool.Index{.none};
7709 const interned = try mod.intern(.{ .anon_struct_type = .{
7710 .names = &names,
7711 .types = &types,
7712 .values = &values,
7713 } });
7714 return interned.toType();
77437715 }
77447716
7745 return if (ret_ty.hasRuntimeBitsIgnoreComptime()) ret_ty else Type.void;
7717 return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void;
77467718}
77477719
7748fn lowersToArray(ty: Type, target: std.Target) bool {
7749 return switch (ty.zigTypeTag()) {
7720fn lowersToArray(ty: Type, mod: *Module) bool {
7721 return switch (ty.zigTypeTag(mod)) {
77507722 .Array, .Vector => return true,
7751 else => return ty.isAbiInt() and toCIntBits(@intCast(u32, ty.bitSize(target))) == null,
7723 else => return ty.isAbiInt(mod) and toCIntBits(@intCast(u32, ty.bitSize(mod))) == null,
77527724 };
77537725}
77547726
......@@ -7765,8 +7737,8 @@ fn reap(f: *Function, inst: Air.Inst.Index, operands: []const Air.Inst.Ref) !voi
77657737
77667738fn die(f: *Function, inst: Air.Inst.Index, ref: Air.Inst.Ref) !void {
77677739 const ref_inst = Air.refToIndex(ref) orelse return;
7740 assert(f.air.instructions.items(.tag)[ref_inst] != .interned);
77687741 const c_value = (f.value_map.fetchRemove(ref_inst) orelse return).value;
7769 if (f.air.instructions.items(.tag)[ref_inst] == .constant) return;
77707742 const local_index = switch (c_value) {
77717743 .local, .new_local => |l| l,
77727744 else => return,
src/codegen/c/type.zig+165-167
......@@ -292,19 +292,19 @@ pub const CType = extern union {
292292 .abi = std.math.log2_int(u32, abi_alignment),
293293 };
294294 }
295 pub fn abiAlign(ty: Type, target: Target) AlignAs {
296 const abi_align = ty.abiAlignment(target);
295 pub fn abiAlign(ty: Type, mod: *Module) AlignAs {
296 const abi_align = ty.abiAlignment(mod);
297297 return init(abi_align, abi_align);
298298 }
299 pub fn fieldAlign(struct_ty: Type, field_i: usize, target: Target) AlignAs {
299 pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs {
300300 return init(
301 struct_ty.structFieldAlign(field_i, target),
302 struct_ty.structFieldType(field_i).abiAlignment(target),
301 struct_ty.structFieldAlign(field_i, mod),
302 struct_ty.structFieldType(field_i, mod).abiAlignment(mod),
303303 );
304304 }
305 pub fn unionPayloadAlign(union_ty: Type, target: Target) AlignAs {
306 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
307 const union_payload_align = union_obj.abiAlignment(target, false);
305 pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs {
306 const union_obj = mod.typeToUnion(union_ty).?;
307 const union_payload_align = union_obj.abiAlignment(mod, false);
308308 return init(union_payload_align, union_payload_align);
309309 }
310310
......@@ -344,8 +344,8 @@ pub const CType = extern union {
344344 return self.map.entries.items(.hash)[index - Tag.no_payload_count];
345345 }
346346
347 pub fn typeToIndex(self: Set, ty: Type, target: Target, kind: Kind) ?Index {
348 const lookup = Convert.Lookup{ .imm = .{ .set = &self, .target = target } };
347 pub fn typeToIndex(self: Set, ty: Type, mod: *Module, kind: Kind) ?Index {
348 const lookup = Convert.Lookup{ .imm = .{ .set = &self, .mod = mod } };
349349
350350 var convert: Convert = undefined;
351351 convert.initType(ty, kind, lookup) catch unreachable;
......@@ -405,7 +405,7 @@ pub const CType = extern union {
405405 );
406406 if (!gop.found_existing) {
407407 errdefer _ = self.set.map.pop();
408 gop.key_ptr.* = try createFromConvert(self, ty, lookup.getTarget(), kind, convert);
408 gop.key_ptr.* = try createFromConvert(self, ty, lookup.getModule(), kind, convert);
409409 }
410410 if (std.debug.runtime_safety) {
411411 const adapter = TypeAdapter64{
......@@ -1236,10 +1236,10 @@ pub const CType = extern union {
12361236 }
12371237
12381238 pub const Lookup = union(enum) {
1239 fail: Target,
1239 fail: *Module,
12401240 imm: struct {
12411241 set: *const Store.Set,
1242 target: Target,
1242 mod: *Module,
12431243 },
12441244 mut: struct {
12451245 promoted: *Store.Promoted,
......@@ -1254,10 +1254,14 @@ pub const CType = extern union {
12541254 }
12551255
12561256 pub fn getTarget(self: @This()) Target {
1257 return self.getModule().getTarget();
1258 }
1259
1260 pub fn getModule(self: @This()) *Module {
12571261 return switch (self) {
1258 .fail => |target| target,
1259 .imm => |imm| imm.target,
1260 .mut => |mut| mut.mod.getTarget(),
1262 .fail => |mod| mod,
1263 .imm => |imm| imm.mod,
1264 .mut => |mut| mut.mod,
12611265 };
12621266 }
12631267
......@@ -1272,7 +1276,7 @@ pub const CType = extern union {
12721276 pub fn typeToIndex(self: @This(), ty: Type, kind: Kind) !?Index {
12731277 return switch (self) {
12741278 .fail => null,
1275 .imm => |imm| imm.set.typeToIndex(ty, imm.target, kind),
1279 .imm => |imm| imm.set.typeToIndex(ty, imm.mod, kind),
12761280 .mut => |mut| try mut.promoted.typeToIndex(ty, mut.mod, kind),
12771281 };
12781282 }
......@@ -1284,7 +1288,7 @@ pub const CType = extern union {
12841288 pub fn freeze(self: @This()) @This() {
12851289 return switch (self) {
12861290 .fail, .imm => self,
1287 .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .target = self.getTarget() } },
1291 .mut => |mut| .{ .imm = .{ .set = &mut.promoted.set, .mod = mut.mod } },
12881292 };
12891293 }
12901294 };
......@@ -1338,7 +1342,7 @@ pub const CType = extern union {
13381342 self.storage.anon.fields[0] = .{
13391343 .name = "array",
13401344 .type = array_idx,
1341 .alignas = AlignAs.abiAlign(ty, lookup.getTarget()),
1345 .alignas = AlignAs.abiAlign(ty, lookup.getModule()),
13421346 };
13431347 self.initAnon(kind, fwd_idx, 1);
13441348 } else self.init(switch (kind) {
......@@ -1350,30 +1354,30 @@ pub const CType = extern union {
13501354 }
13511355
13521356 pub fn initType(self: *@This(), ty: Type, kind: Kind, lookup: Lookup) !void {
1353 const target = lookup.getTarget();
1357 const mod = lookup.getModule();
13541358
13551359 self.* = undefined;
1356 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime())
1360 if (!ty.isFnOrHasRuntimeBitsIgnoreComptime(mod))
13571361 self.init(.void)
1358 else if (ty.isAbiInt()) switch (ty.tag()) {
1359 .usize => self.init(.uintptr_t),
1360 .isize => self.init(.intptr_t),
1361 .c_char => self.init(.char),
1362 .c_short => self.init(.short),
1363 .c_ushort => self.init(.@"unsigned short"),
1364 .c_int => self.init(.int),
1365 .c_uint => self.init(.@"unsigned int"),
1366 .c_long => self.init(.long),
1367 .c_ulong => self.init(.@"unsigned long"),
1368 .c_longlong => self.init(.@"long long"),
1369 .c_ulonglong => self.init(.@"unsigned long long"),
1370 else => switch (tagFromIntInfo(ty.intInfo(target))) {
1362 else if (ty.isAbiInt(mod)) switch (ty.ip_index) {
1363 .usize_type => self.init(.uintptr_t),
1364 .isize_type => self.init(.intptr_t),
1365 .c_char_type => self.init(.char),
1366 .c_short_type => self.init(.short),
1367 .c_ushort_type => self.init(.@"unsigned short"),
1368 .c_int_type => self.init(.int),
1369 .c_uint_type => self.init(.@"unsigned int"),
1370 .c_long_type => self.init(.long),
1371 .c_ulong_type => self.init(.@"unsigned long"),
1372 .c_longlong_type => self.init(.@"long long"),
1373 .c_ulonglong_type => self.init(.@"unsigned long long"),
1374 else => switch (tagFromIntInfo(ty.intInfo(mod))) {
13711375 .void => unreachable,
13721376 else => |t| self.init(t),
13731377 .array => switch (kind) {
13741378 .forward, .complete, .global => {
1375 const abi_size = ty.abiSize(target);
1376 const abi_align = ty.abiAlignment(target);
1379 const abi_size = ty.abiSize(mod);
1380 const abi_align = ty.abiAlignment(mod);
13771381 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
13781382 .len = @divExact(abi_size, abi_align),
13791383 .elem_type = tagFromIntInfo(.{
......@@ -1389,7 +1393,7 @@ pub const CType = extern union {
13891393 .payload => unreachable,
13901394 },
13911395 },
1392 } else switch (ty.zigTypeTag()) {
1396 } else switch (ty.zigTypeTag(mod)) {
13931397 .Frame => unreachable,
13941398 .AnyFrame => unreachable,
13951399
......@@ -1408,18 +1412,18 @@ pub const CType = extern union {
14081412
14091413 .Bool => self.init(.bool),
14101414
1411 .Float => self.init(switch (ty.tag()) {
1412 .f16 => .zig_f16,
1413 .f32 => .zig_f32,
1414 .f64 => .zig_f64,
1415 .f80 => .zig_f80,
1416 .f128 => .zig_f128,
1417 .c_longdouble => .zig_c_longdouble,
1415 .Float => self.init(switch (ty.ip_index) {
1416 .f16_type => .zig_f16,
1417 .f32_type => .zig_f32,
1418 .f64_type => .zig_f64,
1419 .f80_type => .zig_f80,
1420 .f128_type => .zig_f128,
1421 .c_longdouble_type => .zig_c_longdouble,
14181422 else => unreachable,
14191423 }),
14201424
14211425 .Pointer => {
1422 const info = ty.ptrInfo().data;
1426 const info = ty.ptrInfo(mod);
14231427 switch (info.size) {
14241428 .Slice => {
14251429 if (switch (kind) {
......@@ -1427,19 +1431,18 @@ pub const CType = extern union {
14271431 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
14281432 .payload => unreachable,
14291433 }) |fwd_idx| {
1430 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1431 const ptr_ty = ty.slicePtrFieldType(&buf);
1434 const ptr_ty = ty.slicePtrFieldType(mod);
14321435 if (try lookup.typeToIndex(ptr_ty, kind)) |ptr_idx| {
14331436 self.storage = .{ .anon = undefined };
14341437 self.storage.anon.fields[0] = .{
14351438 .name = "ptr",
14361439 .type = ptr_idx,
1437 .alignas = AlignAs.abiAlign(ptr_ty, target),
1440 .alignas = AlignAs.abiAlign(ptr_ty, mod),
14381441 };
14391442 self.storage.anon.fields[1] = .{
14401443 .name = "len",
14411444 .type = Tag.uintptr_t.toIndex(),
1442 .alignas = AlignAs.abiAlign(Type.usize, target),
1445 .alignas = AlignAs.abiAlign(Type.usize, mod),
14431446 };
14441447 self.initAnon(kind, fwd_idx, 2);
14451448 } else self.init(switch (kind) {
......@@ -1462,16 +1465,12 @@ pub const CType = extern union {
14621465 },
14631466 };
14641467
1465 var host_int_pl = Type.Payload.Bits{
1466 .base = .{ .tag = .int_unsigned },
1467 .data = info.host_size * 8,
1468 };
14691468 const pointee_ty = if (info.host_size > 0 and info.vector_index == .none)
1470 Type.initPayload(&host_int_pl.base)
1469 try mod.intType(.unsigned, info.host_size * 8)
14711470 else
14721471 info.pointee_type;
14731472
1474 if (if (info.size == .C and pointee_ty.tag() == .u8)
1473 if (if (info.size == .C and pointee_ty.ip_index == .u8_type)
14751474 Tag.char.toIndex()
14761475 else
14771476 try lookup.typeToIndex(pointee_ty, .forward)) |child_idx|
......@@ -1486,26 +1485,24 @@ pub const CType = extern union {
14861485 }
14871486 },
14881487
1489 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout() == .Packed) {
1490 if (ty.castTag(.@"struct")) |struct_obj| {
1491 try self.initType(struct_obj.data.backing_int_ty, kind, lookup);
1488 .Struct, .Union => |zig_ty_tag| if (ty.containerLayout(mod) == .Packed) {
1489 if (mod.typeToStruct(ty)) |struct_obj| {
1490 try self.initType(struct_obj.backing_int_ty, kind, lookup);
14921491 } else {
1493 var buf: Type.Payload.Bits = .{
1494 .base = .{ .tag = .int_unsigned },
1495 .data = @intCast(u16, ty.bitSize(target)),
1496 };
1497 try self.initType(Type.initPayload(&buf.base), kind, lookup);
1492 const bits = @intCast(u16, ty.bitSize(mod));
1493 const int_ty = try mod.intType(.unsigned, bits);
1494 try self.initType(int_ty, kind, lookup);
14981495 }
1499 } else if (ty.isTupleOrAnonStruct()) {
1496 } else if (ty.isTupleOrAnonStruct(mod)) {
15001497 if (lookup.isMutable()) {
15011498 for (0..switch (zig_ty_tag) {
1502 .Struct => ty.structFieldCount(),
1503 .Union => ty.unionFields().count(),
1499 .Struct => ty.structFieldCount(mod),
1500 .Union => ty.unionFields(mod).count(),
15041501 else => unreachable,
15051502 }) |field_i| {
1506 const field_ty = ty.structFieldType(field_i);
1507 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
1508 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1503 const field_ty = ty.structFieldType(field_i, mod);
1504 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1505 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
15091506 _ = try lookup.typeToIndex(field_ty, switch (kind) {
15101507 .forward, .forward_parameter => .forward,
15111508 .complete, .parameter => .complete,
......@@ -1533,14 +1530,14 @@ pub const CType = extern union {
15331530 .payload => unreachable,
15341531 });
15351532 } else {
1536 const tag_ty = ty.unionTagTypeSafety();
1533 const tag_ty = ty.unionTagTypeSafety(mod);
15371534 const is_tagged_union_wrapper = kind != .payload and tag_ty != null;
15381535 const is_struct = zig_ty_tag == .Struct or is_tagged_union_wrapper;
15391536 switch (kind) {
15401537 .forward, .forward_parameter => {
15411538 self.storage = .{ .fwd = .{
15421539 .base = .{ .tag = if (is_struct) .fwd_struct else .fwd_union },
1543 .data = ty.getOwnerDecl(),
1540 .data = ty.getOwnerDecl(mod),
15441541 } };
15451542 self.value = .{ .cty = initPayload(&self.storage.fwd) };
15461543 },
......@@ -1555,7 +1552,7 @@ pub const CType = extern union {
15551552 self.storage.anon.fields[field_count] = .{
15561553 .name = "payload",
15571554 .type = payload_idx.?,
1558 .alignas = AlignAs.unionPayloadAlign(ty, target),
1555 .alignas = AlignAs.unionPayloadAlign(ty, mod),
15591556 };
15601557 field_count += 1;
15611558 }
......@@ -1563,7 +1560,7 @@ pub const CType = extern union {
15631560 self.storage.anon.fields[field_count] = .{
15641561 .name = "tag",
15651562 .type = tag_idx.?,
1566 .alignas = AlignAs.abiAlign(tag_ty.?, target),
1563 .alignas = AlignAs.abiAlign(tag_ty.?, mod),
15671564 };
15681565 field_count += 1;
15691566 }
......@@ -1576,19 +1573,19 @@ pub const CType = extern union {
15761573 } };
15771574 self.value = .{ .cty = initPayload(&self.storage.anon.pl.complete) };
15781575 } else self.init(.@"struct");
1579 } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes()) {
1576 } else if (kind == .payload and ty.unionHasAllZeroBitFieldTypes(mod)) {
15801577 self.init(.void);
15811578 } else {
15821579 var is_packed = false;
15831580 for (0..switch (zig_ty_tag) {
1584 .Struct => ty.structFieldCount(),
1585 .Union => ty.unionFields().count(),
1581 .Struct => ty.structFieldCount(mod),
1582 .Union => ty.unionFields(mod).count(),
15861583 else => unreachable,
15871584 }) |field_i| {
1588 const field_ty = ty.structFieldType(field_i);
1589 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1585 const field_ty = ty.structFieldType(field_i, mod);
1586 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
15901587
1591 const field_align = AlignAs.fieldAlign(ty, field_i, target);
1588 const field_align = AlignAs.fieldAlign(ty, field_i, mod);
15921589 if (field_align.@"align" < field_align.abi) {
15931590 is_packed = true;
15941591 if (!lookup.isMutable()) break;
......@@ -1627,9 +1624,9 @@ pub const CType = extern union {
16271624 .Vector => .vector,
16281625 else => unreachable,
16291626 };
1630 if (try lookup.typeToIndex(ty.childType(), kind)) |child_idx| {
1627 if (try lookup.typeToIndex(ty.childType(mod), kind)) |child_idx| {
16311628 self.storage = .{ .seq = .{ .base = .{ .tag = t }, .data = .{
1632 .len = ty.arrayLenIncludingSentinel(),
1629 .len = ty.arrayLenIncludingSentinel(mod),
16331630 .elem_type = child_idx,
16341631 } } };
16351632 self.value = .{ .cty = initPayload(&self.storage.seq) };
......@@ -1641,10 +1638,9 @@ pub const CType = extern union {
16411638 },
16421639
16431640 .Optional => {
1644 var buf: Type.Payload.ElemType = undefined;
1645 const payload_ty = ty.optionalChild(&buf);
1646 if (payload_ty.hasRuntimeBitsIgnoreComptime()) {
1647 if (ty.optionalReprIsPayload()) {
1641 const payload_ty = ty.optionalChild(mod);
1642 if (payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1643 if (ty.optionalReprIsPayload(mod)) {
16481644 try self.initType(payload_ty, kind, lookup);
16491645 } else if (switch (kind) {
16501646 .forward, .forward_parameter => @as(Index, undefined),
......@@ -1661,12 +1657,12 @@ pub const CType = extern union {
16611657 self.storage.anon.fields[0] = .{
16621658 .name = "payload",
16631659 .type = payload_idx,
1664 .alignas = AlignAs.abiAlign(payload_ty, target),
1660 .alignas = AlignAs.abiAlign(payload_ty, mod),
16651661 };
16661662 self.storage.anon.fields[1] = .{
16671663 .name = "is_null",
16681664 .type = Tag.bool.toIndex(),
1669 .alignas = AlignAs.abiAlign(Type.bool, target),
1665 .alignas = AlignAs.abiAlign(Type.bool, mod),
16701666 };
16711667 self.initAnon(kind, fwd_idx, 2);
16721668 } else self.init(switch (kind) {
......@@ -1684,14 +1680,14 @@ pub const CType = extern union {
16841680 .complete, .parameter, .global => try lookup.typeToIndex(ty, .forward),
16851681 .payload => unreachable,
16861682 }) |fwd_idx| {
1687 const payload_ty = ty.errorUnionPayload();
1683 const payload_ty = ty.errorUnionPayload(mod);
16881684 if (try lookup.typeToIndex(payload_ty, switch (kind) {
16891685 .forward, .forward_parameter => .forward,
16901686 .complete, .parameter => .complete,
16911687 .global => .global,
16921688 .payload => unreachable,
16931689 })) |payload_idx| {
1694 const error_ty = ty.errorUnionSet();
1690 const error_ty = ty.errorUnionSet(mod);
16951691 if (payload_idx == Tag.void.toIndex()) {
16961692 try self.initType(error_ty, kind, lookup);
16971693 } else if (try lookup.typeToIndex(error_ty, kind)) |error_idx| {
......@@ -1699,12 +1695,12 @@ pub const CType = extern union {
16991695 self.storage.anon.fields[0] = .{
17001696 .name = "payload",
17011697 .type = payload_idx,
1702 .alignas = AlignAs.abiAlign(payload_ty, target),
1698 .alignas = AlignAs.abiAlign(payload_ty, mod),
17031699 };
17041700 self.storage.anon.fields[1] = .{
17051701 .name = "error",
17061702 .type = error_idx,
1707 .alignas = AlignAs.abiAlign(error_ty, target),
1703 .alignas = AlignAs.abiAlign(error_ty, mod),
17081704 };
17091705 self.initAnon(kind, fwd_idx, 2);
17101706 } else self.init(switch (kind) {
......@@ -1723,7 +1719,7 @@ pub const CType = extern union {
17231719 .Opaque => self.init(.void),
17241720
17251721 .Fn => {
1726 const info = ty.fnInfo();
1722 const info = mod.typeToFunc(ty).?;
17271723 if (!info.is_generic) {
17281724 if (lookup.isMutable()) {
17291725 const param_kind: Kind = switch (kind) {
......@@ -1731,10 +1727,10 @@ pub const CType = extern union {
17311727 .complete, .parameter, .global => .parameter,
17321728 .payload => unreachable,
17331729 };
1734 _ = try lookup.typeToIndex(info.return_type, param_kind);
1730 _ = try lookup.typeToIndex(info.return_type.toType(), param_kind);
17351731 for (info.param_types) |param_type| {
1736 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
1737 _ = try lookup.typeToIndex(param_type, param_kind);
1732 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
1733 _ = try lookup.typeToIndex(param_type.toType(), param_kind);
17381734 }
17391735 }
17401736 self.init(if (info.is_var_args) .varargs_function else .function);
......@@ -1900,16 +1896,16 @@ pub const CType = extern union {
19001896 }
19011897 }
19021898
1903 fn createFromType(store: *Store.Promoted, ty: Type, target: Target, kind: Kind) !CType {
1899 fn createFromType(store: *Store.Promoted, ty: Type, mod: *Module, kind: Kind) !CType {
19041900 var convert: Convert = undefined;
1905 try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .target = target } });
1906 return createFromConvert(store, ty, target, kind, &convert);
1901 try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } });
1902 return createFromConvert(store, ty, mod, kind, &convert);
19071903 }
19081904
19091905 fn createFromConvert(
19101906 store: *Store.Promoted,
19111907 ty: Type,
1912 target: Target,
1908 mod: *Module,
19131909 kind: Kind,
19141910 convert: Convert,
19151911 ) !CType {
......@@ -1930,44 +1926,44 @@ pub const CType = extern union {
19301926 .packed_struct,
19311927 .packed_union,
19321928 => {
1933 const zig_ty_tag = ty.zigTypeTag();
1929 const zig_ty_tag = ty.zigTypeTag(mod);
19341930 const fields_len = switch (zig_ty_tag) {
1935 .Struct => ty.structFieldCount(),
1936 .Union => ty.unionFields().count(),
1931 .Struct => ty.structFieldCount(mod),
1932 .Union => ty.unionFields(mod).count(),
19371933 else => unreachable,
19381934 };
19391935
19401936 var c_fields_len: usize = 0;
19411937 for (0..fields_len) |field_i| {
1942 const field_ty = ty.structFieldType(field_i);
1943 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
1944 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1938 const field_ty = ty.structFieldType(field_i, mod);
1939 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1940 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
19451941 c_fields_len += 1;
19461942 }
19471943
19481944 const fields_pl = try arena.alloc(Payload.Fields.Field, c_fields_len);
19491945 var c_field_i: usize = 0;
19501946 for (0..fields_len) |field_i| {
1951 const field_ty = ty.structFieldType(field_i);
1952 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
1953 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
1947 const field_ty = ty.structFieldType(field_i, mod);
1948 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
1949 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
19541950
19551951 defer c_field_i += 1;
19561952 fields_pl[c_field_i] = .{
1957 .name = try if (ty.isSimpleTuple())
1953 .name = try if (ty.isSimpleTuple(mod))
19581954 std.fmt.allocPrintZ(arena, "f{}", .{field_i})
19591955 else
1960 arena.dupeZ(u8, switch (zig_ty_tag) {
1961 .Struct => ty.structFieldName(field_i),
1962 .Union => ty.unionFields().keys()[field_i],
1956 arena.dupeZ(u8, mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
1957 .Struct => ty.structFieldName(field_i, mod),
1958 .Union => ty.unionFields(mod).keys()[field_i],
19631959 else => unreachable,
1964 }),
1965 .type = store.set.typeToIndex(field_ty, target, switch (kind) {
1960 })),
1961 .type = store.set.typeToIndex(field_ty, mod, switch (kind) {
19661962 .forward, .forward_parameter => .forward,
19671963 .complete, .parameter, .payload => .complete,
19681964 .global => .global,
19691965 }).?,
1970 .alignas = AlignAs.fieldAlign(ty, field_i, target),
1966 .alignas = AlignAs.fieldAlign(ty, field_i, mod),
19711967 };
19721968 }
19731969
......@@ -1988,8 +1984,8 @@ pub const CType = extern union {
19881984 const unnamed_pl = try arena.create(Payload.Unnamed);
19891985 unnamed_pl.* = .{ .base = .{ .tag = t }, .data = .{
19901986 .fields = fields_pl,
1991 .owner_decl = ty.getOwnerDecl(),
1992 .id = if (ty.unionTagTypeSafety()) |_| 0 else unreachable,
1987 .owner_decl = ty.getOwnerDecl(mod),
1988 .id = if (ty.unionTagTypeSafety(mod)) |_| 0 else unreachable,
19931989 } };
19941990 return initPayload(unnamed_pl);
19951991 },
......@@ -2004,7 +2000,7 @@ pub const CType = extern union {
20042000 const struct_pl = try arena.create(Payload.Aggregate);
20052001 struct_pl.* = .{ .base = .{ .tag = t }, .data = .{
20062002 .fields = fields_pl,
2007 .fwd_decl = store.set.typeToIndex(ty, target, .forward).?,
2003 .fwd_decl = store.set.typeToIndex(ty, mod, .forward).?,
20082004 } };
20092005 return initPayload(struct_pl);
20102006 },
......@@ -2016,7 +2012,7 @@ pub const CType = extern union {
20162012 .function,
20172013 .varargs_function,
20182014 => {
2019 const info = ty.fnInfo();
2015 const info = mod.typeToFunc(ty).?;
20202016 assert(!info.is_generic);
20212017 const param_kind: Kind = switch (kind) {
20222018 .forward, .forward_parameter => .forward_parameter,
......@@ -2026,21 +2022,21 @@ pub const CType = extern union {
20262022
20272023 var c_params_len: usize = 0;
20282024 for (info.param_types) |param_type| {
2029 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
2025 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
20302026 c_params_len += 1;
20312027 }
20322028
20332029 const params_pl = try arena.alloc(Index, c_params_len);
20342030 var c_param_i: usize = 0;
20352031 for (info.param_types) |param_type| {
2036 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
2037 params_pl[c_param_i] = store.set.typeToIndex(param_type, target, param_kind).?;
2032 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2033 params_pl[c_param_i] = store.set.typeToIndex(param_type.toType(), mod, param_kind).?;
20382034 c_param_i += 1;
20392035 }
20402036
20412037 const fn_pl = try arena.create(Payload.Function);
20422038 fn_pl.* = .{ .base = .{ .tag = t }, .data = .{
2043 .return_type = store.set.typeToIndex(info.return_type, target, param_kind).?,
2039 .return_type = store.set.typeToIndex(info.return_type.toType(), mod, param_kind).?,
20442040 .param_types = params_pl,
20452041 } };
20462042 return initPayload(fn_pl);
......@@ -2067,33 +2063,33 @@ pub const CType = extern union {
20672063 }
20682064
20692065 pub fn eql(self: @This(), ty: Type, cty: CType) bool {
2066 const mod = self.lookup.getModule();
20702067 switch (self.convert.value) {
20712068 .cty => |c| return c.eql(cty),
20722069 .tag => |t| {
20732070 if (t != cty.tag()) return false;
20742071
2075 const target = self.lookup.getTarget();
20762072 switch (t) {
20772073 .fwd_anon_struct,
20782074 .fwd_anon_union,
20792075 => {
2080 if (!ty.isTupleOrAnonStruct()) return false;
2076 if (!ty.isTupleOrAnonStruct(mod)) return false;
20812077
20822078 var name_buf: [
20832079 std.fmt.count("f{}", .{std.math.maxInt(usize)})
20842080 ]u8 = undefined;
20852081 const c_fields = cty.cast(Payload.Fields).?.data;
20862082
2087 const zig_ty_tag = ty.zigTypeTag();
2083 const zig_ty_tag = ty.zigTypeTag(mod);
20882084 var c_field_i: usize = 0;
20892085 for (0..switch (zig_ty_tag) {
2090 .Struct => ty.structFieldCount(),
2091 .Union => ty.unionFields().count(),
2086 .Struct => ty.structFieldCount(mod),
2087 .Union => ty.unionFields(mod).count(),
20922088 else => unreachable,
20932089 }) |field_i| {
2094 const field_ty = ty.structFieldType(field_i);
2095 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
2096 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
2090 const field_ty = ty.structFieldType(field_i, mod);
2091 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
2092 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
20972093
20982094 defer c_field_i += 1;
20992095 const c_field = &c_fields[c_field_i];
......@@ -2105,15 +2101,16 @@ pub const CType = extern union {
21052101 .payload => unreachable,
21062102 }) or !mem.eql(
21072103 u8,
2108 if (ty.isSimpleTuple())
2109 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
2110 else switch (zig_ty_tag) {
2111 .Struct => ty.structFieldName(field_i),
2112 .Union => ty.unionFields().keys()[field_i],
2113 else => unreachable,
2114 },
2104 if (ty.isSimpleTuple(mod))
2105 std.fmt.bufPrintZ(&name_buf, "f{}", .{field_i}) catch unreachable
2106 else
2107 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
2108 .Struct => ty.structFieldName(field_i, mod),
2109 .Union => ty.unionFields(mod).keys()[field_i],
2110 else => unreachable,
2111 }),
21152112 mem.span(c_field.name),
2116 ) or AlignAs.fieldAlign(ty, field_i, target).@"align" !=
2113 ) or AlignAs.fieldAlign(ty, field_i, mod).@"align" !=
21172114 c_field.alignas.@"align") return false;
21182115 }
21192116 return true;
......@@ -2125,9 +2122,9 @@ pub const CType = extern union {
21252122 .packed_unnamed_union,
21262123 => switch (self.kind) {
21272124 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
2128 .payload => if (ty.unionTagTypeSafety()) |_| {
2125 .payload => if (ty.unionTagTypeSafety(mod)) |_| {
21292126 const data = cty.cast(Payload.Unnamed).?.data;
2130 return ty.getOwnerDecl() == data.owner_decl and data.id == 0;
2127 return ty.getOwnerDecl(mod) == data.owner_decl and data.id == 0;
21312128 } else unreachable,
21322129 },
21332130
......@@ -2146,9 +2143,9 @@ pub const CType = extern union {
21462143 .function,
21472144 .varargs_function,
21482145 => {
2149 if (ty.zigTypeTag() != .Fn) return false;
2146 if (ty.zigTypeTag(mod) != .Fn) return false;
21502147
2151 const info = ty.fnInfo();
2148 const info = mod.typeToFunc(ty).?;
21522149 assert(!info.is_generic);
21532150 const data = cty.cast(Payload.Function).?.data;
21542151 const param_kind: Kind = switch (self.kind) {
......@@ -2157,18 +2154,18 @@ pub const CType = extern union {
21572154 .payload => unreachable,
21582155 };
21592156
2160 if (!self.eqlRecurse(info.return_type, data.return_type, param_kind))
2157 if (!self.eqlRecurse(info.return_type.toType(), data.return_type, param_kind))
21612158 return false;
21622159
21632160 var c_param_i: usize = 0;
21642161 for (info.param_types) |param_type| {
2165 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
2162 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
21662163
21672164 if (c_param_i >= data.param_types.len) return false;
21682165 const param_cty = data.param_types[c_param_i];
21692166 c_param_i += 1;
21702167
2171 if (!self.eqlRecurse(param_type, param_cty, param_kind))
2168 if (!self.eqlRecurse(param_type.toType(), param_cty, param_kind))
21722169 return false;
21732170 }
21742171 return c_param_i == data.param_types.len;
......@@ -2202,7 +2199,7 @@ pub const CType = extern union {
22022199 .tag => |t| {
22032200 autoHash(hasher, t);
22042201
2205 const target = self.lookup.getTarget();
2202 const mod = self.lookup.getModule();
22062203 switch (t) {
22072204 .fwd_anon_struct,
22082205 .fwd_anon_union,
......@@ -2211,15 +2208,15 @@ pub const CType = extern union {
22112208 std.fmt.count("f{}", .{std.math.maxInt(usize)})
22122209 ]u8 = undefined;
22132210
2214 const zig_ty_tag = ty.zigTypeTag();
2215 for (0..switch (ty.zigTypeTag()) {
2216 .Struct => ty.structFieldCount(),
2217 .Union => ty.unionFields().count(),
2211 const zig_ty_tag = ty.zigTypeTag(mod);
2212 for (0..switch (ty.zigTypeTag(mod)) {
2213 .Struct => ty.structFieldCount(mod),
2214 .Union => ty.unionFields(mod).count(),
22182215 else => unreachable,
22192216 }) |field_i| {
2220 const field_ty = ty.structFieldType(field_i);
2221 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i)) or
2222 !field_ty.hasRuntimeBitsIgnoreComptime()) continue;
2217 const field_ty = ty.structFieldType(field_i, mod);
2218 if ((zig_ty_tag == .Struct and ty.structFieldIsComptime(field_i, mod)) or
2219 !field_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22232220
22242221 self.updateHasherRecurse(hasher, field_ty, switch (self.kind) {
22252222 .forward, .forward_parameter => .forward,
......@@ -2227,14 +2224,15 @@ pub const CType = extern union {
22272224 .global => .global,
22282225 .payload => unreachable,
22292226 });
2230 hasher.update(if (ty.isSimpleTuple())
2227 hasher.update(if (ty.isSimpleTuple(mod))
22312228 std.fmt.bufPrint(&name_buf, "f{}", .{field_i}) catch unreachable
2232 else switch (zig_ty_tag) {
2233 .Struct => ty.structFieldName(field_i),
2234 .Union => ty.unionFields().keys()[field_i],
2235 else => unreachable,
2236 });
2237 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, target).@"align");
2229 else
2230 mod.intern_pool.stringToSlice(switch (zig_ty_tag) {
2231 .Struct => ty.structFieldName(field_i, mod),
2232 .Union => ty.unionFields(mod).keys()[field_i],
2233 else => unreachable,
2234 }));
2235 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, mod).@"align");
22382236 }
22392237 },
22402238
......@@ -2244,8 +2242,8 @@ pub const CType = extern union {
22442242 .packed_unnamed_union,
22452243 => switch (self.kind) {
22462244 .forward, .forward_parameter, .complete, .parameter, .global => unreachable,
2247 .payload => if (ty.unionTagTypeSafety()) |_| {
2248 autoHash(hasher, ty.getOwnerDecl());
2245 .payload => if (ty.unionTagTypeSafety(mod)) |_| {
2246 autoHash(hasher, ty.getOwnerDecl(mod));
22492247 autoHash(hasher, @as(u32, 0));
22502248 } else unreachable,
22512249 },
......@@ -2261,7 +2259,7 @@ pub const CType = extern union {
22612259 .function,
22622260 .varargs_function,
22632261 => {
2264 const info = ty.fnInfo();
2262 const info = mod.typeToFunc(ty).?;
22652263 assert(!info.is_generic);
22662264 const param_kind: Kind = switch (self.kind) {
22672265 .forward, .forward_parameter => .forward_parameter,
......@@ -2269,10 +2267,10 @@ pub const CType = extern union {
22692267 .payload => unreachable,
22702268 };
22712269
2272 self.updateHasherRecurse(hasher, info.return_type, param_kind);
2270 self.updateHasherRecurse(hasher, info.return_type.toType(), param_kind);
22732271 for (info.param_types) |param_type| {
2274 if (!param_type.hasRuntimeBitsIgnoreComptime()) continue;
2275 self.updateHasherRecurse(hasher, param_type, param_kind);
2272 if (!param_type.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
2273 self.updateHasherRecurse(hasher, param_type.toType(), param_kind);
22762274 }
22772275 },
22782276
src/codegen/llvm.zig+2024-2211
......@@ -12,6 +12,7 @@ const link = @import("../link.zig");
1212const Compilation = @import("../Compilation.zig");
1313const build_options = @import("build_options");
1414const Module = @import("../Module.zig");
15const InternPool = @import("../InternPool.zig");
1516const Package = @import("../Package.zig");
1617const TypedValue = @import("../TypedValue.zig");
1718const Air = @import("../Air.zig");
......@@ -361,15 +362,11 @@ pub const Object = struct {
361362 decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),
362363 /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.
363364 named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, *llvm.Value),
364 /// Maps Zig types to LLVM types. The table memory itself is backed by the GPA of
365 /// the compiler, but the Type/Value memory here is backed by `type_map_arena`.
366 /// TODO we need to remove entries from this map in response to incremental compilation
367 /// but I think the frontend won't tell us about types that get deleted because
368 /// hasRuntimeBits() is false for types.
365 /// Maps Zig types to LLVM types. The table memory is backed by the GPA of
366 /// the compiler.
367 /// TODO when InternPool garbage collection is implemented, this map needs
368 /// to be garbage collected as well.
369369 type_map: TypeMap,
370 /// The backing memory for `type_map`. Periodically garbage collected after flush().
371 /// The code for doing the periodical GC is not yet implemented.
372 type_map_arena: std.heap.ArenaAllocator,
373370 di_type_map: DITypeMap,
374371 /// The LLVM global table which holds the names corresponding to Zig errors.
375372 /// Note that the values are not added until flushModule, when all errors in
......@@ -380,21 +377,11 @@ pub const Object = struct {
380377 /// name collision.
381378 extern_collisions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void),
382379
383 pub const TypeMap = std.HashMapUnmanaged(
384 Type,
385 *llvm.Type,
386 Type.HashContext64,
387 std.hash_map.default_max_load_percentage,
388 );
380 pub const TypeMap = std.AutoHashMapUnmanaged(InternPool.Index, *llvm.Type);
389381
390382 /// This is an ArrayHashMap as opposed to a HashMap because in `flushModule` we
391383 /// want to iterate over it while adding entries to it.
392 pub const DITypeMap = std.ArrayHashMapUnmanaged(
393 Type,
394 AnnotatedDITypePtr,
395 Type.HashContext32,
396 true,
397 );
384 pub const DITypeMap = std.AutoArrayHashMapUnmanaged(InternPool.Index, AnnotatedDITypePtr);
398385
399386 pub fn create(gpa: Allocator, options: link.Options) !*Object {
400387 const obj = try gpa.create(Object);
......@@ -542,7 +529,6 @@ pub const Object = struct {
542529 .decl_map = .{},
543530 .named_enum_map = .{},
544531 .type_map = .{},
545 .type_map_arena = std.heap.ArenaAllocator.init(gpa),
546532 .di_type_map = .{},
547533 .error_name_table = null,
548534 .extern_collisions = .{},
......@@ -562,7 +548,6 @@ pub const Object = struct {
562548 self.decl_map.deinit(gpa);
563549 self.named_enum_map.deinit(gpa);
564550 self.type_map.deinit(gpa);
565 self.type_map_arena.deinit();
566551 self.extern_collisions.deinit(gpa);
567552 self.* = undefined;
568553 }
......@@ -597,16 +582,16 @@ pub const Object = struct {
597582 llvm_usize_ty,
598583 };
599584 const llvm_slice_ty = self.context.structType(&type_fields, type_fields.len, .False);
600 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
601 const slice_alignment = slice_ty.abiAlignment(target);
585 const slice_ty = Type.slice_const_u8_sentinel_0;
586 const slice_alignment = slice_ty.abiAlignment(mod);
602587
603 const error_name_list = mod.error_name_list.items;
588 const error_name_list = mod.global_error_set.keys();
604589 const llvm_errors = try mod.gpa.alloc(*llvm.Value, error_name_list.len);
605590 defer mod.gpa.free(llvm_errors);
606591
607592 llvm_errors[0] = llvm_slice_ty.getUndef();
608 for (llvm_errors[1..], 0..) |*llvm_error, i| {
609 const name = error_name_list[1..][i];
593 for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name_nts| {
594 const name = mod.intern_pool.stringToSlice(name_nts);
610595 const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False);
611596 const str_global = self.llvm_module.addGlobal(str_init.typeOf(), "");
612597 str_global.setInitializer(str_init);
......@@ -686,7 +671,7 @@ pub const Object = struct {
686671 const llvm_global = entry.value_ptr.*;
687672 // Same logic as below but for externs instead of exports.
688673 const decl = mod.declPtr(decl_index);
689 const other_global = object.getLlvmGlobal(decl.name) orelse continue;
674 const other_global = object.getLlvmGlobal(mod.intern_pool.stringToSlice(decl.name)) orelse continue;
690675 if (other_global == llvm_global) continue;
691676
692677 llvm_global.replaceAllUsesWith(other_global);
......@@ -702,12 +687,9 @@ pub const Object = struct {
702687 for (export_list.items) |exp| {
703688 // Detect if the LLVM global has already been created as an extern. In such
704689 // case, we need to replace all uses of it with this exported global.
705 // TODO update std.builtin.ExportOptions to have the name be a
706 // null-terminated slice.
707 const exp_name_z = try mod.gpa.dupeZ(u8, exp.options.name);
708 defer mod.gpa.free(exp_name_z);
690 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
709691
710 const other_global = object.getLlvmGlobal(exp_name_z.ptr) orelse continue;
692 const other_global = object.getLlvmGlobal(exp_name.ptr) orelse continue;
711693 if (other_global == llvm_global) continue;
712694
713695 other_global.replaceAllUsesWith(llvm_global);
......@@ -880,28 +862,29 @@ pub const Object = struct {
880862
881863 pub fn updateFunc(
882864 o: *Object,
883 module: *Module,
884 func: *Module.Fn,
865 mod: *Module,
866 func_index: Module.Fn.Index,
885867 air: Air,
886868 liveness: Liveness,
887869 ) !void {
870 const func = mod.funcPtr(func_index);
888871 const decl_index = func.owner_decl;
889 const decl = module.declPtr(decl_index);
890 const target = module.getTarget();
872 const decl = mod.declPtr(decl_index);
873 const target = mod.getTarget();
891874
892875 var dg: DeclGen = .{
893876 .context = o.context,
894877 .object = o,
895 .module = module,
878 .module = mod,
896879 .decl_index = decl_index,
897880 .decl = decl,
898881 .err_msg = null,
899 .gpa = module.gpa,
882 .gpa = mod.gpa,
900883 };
901884
902885 const llvm_func = try dg.resolveLlvmFunction(decl_index);
903886
904 if (module.align_stack_fns.get(func)) |align_info| {
887 if (mod.align_stack_fns.get(func_index)) |align_info| {
905888 dg.addFnAttrInt(llvm_func, "alignstack", align_info.alignment);
906889 dg.addFnAttr(llvm_func, "noinline");
907890 } else {
......@@ -922,7 +905,7 @@ pub const Object = struct {
922905 }
923906
924907 // TODO: disable this if safety is off for the function scope
925 const ssp_buf_size = module.comp.bin_file.options.stack_protector;
908 const ssp_buf_size = mod.comp.bin_file.options.stack_protector;
926909 if (ssp_buf_size != 0) {
927910 var buf: [12]u8 = undefined;
928911 const arg = std.fmt.bufPrintZ(&buf, "{d}", .{ssp_buf_size}) catch unreachable;
......@@ -931,15 +914,14 @@ pub const Object = struct {
931914 }
932915
933916 // TODO: disable this if safety is off for the function scope
934 if (module.comp.bin_file.options.stack_check) {
917 if (mod.comp.bin_file.options.stack_check) {
935918 dg.addFnAttrString(llvm_func, "probe-stack", "__zig_probe_stack");
936919 } else if (target.os.tag == .uefi) {
937920 dg.addFnAttrString(llvm_func, "no-stack-arg-probe", "");
938921 }
939922
940 if (decl.@"linksection") |section| {
923 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |section|
941924 llvm_func.setSection(section);
942 }
943925
944926 // Remove all the basic blocks of a function in order to start over, generating
945927 // LLVM IR from an empty function body.
......@@ -953,18 +935,18 @@ pub const Object = struct {
953935 builder.positionBuilderAtEnd(entry_block);
954936
955937 // This gets the LLVM values from the function and stores them in `dg.args`.
956 const fn_info = decl.ty.fnInfo();
957 const sret = firstParamSRet(fn_info, target);
938 const fn_info = mod.typeToFunc(decl.ty).?;
939 const sret = firstParamSRet(fn_info, mod);
958940 const ret_ptr = if (sret) llvm_func.getParam(0) else null;
959941 const gpa = dg.gpa;
960942
961 if (ccAbiPromoteInt(fn_info.cc, target, fn_info.return_type)) |s| switch (s) {
943 if (ccAbiPromoteInt(fn_info.cc, mod, fn_info.return_type.toType())) |s| switch (s) {
962944 .signed => dg.addAttr(llvm_func, 0, "signext"),
963945 .unsigned => dg.addAttr(llvm_func, 0, "zeroext"),
964946 };
965947
966 const err_return_tracing = fn_info.return_type.isError() and
967 module.comp.bin_file.options.error_return_tracing;
948 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
949 mod.comp.bin_file.options.error_return_tracing;
968950
969951 const err_ret_trace = if (err_return_tracing)
970952 llvm_func.getParam(@boolToInt(ret_ptr != null))
......@@ -985,12 +967,12 @@ pub const Object = struct {
985967 .byval => {
986968 assert(!it.byval_attr);
987969 const param_index = it.zig_index - 1;
988 const param_ty = fn_info.param_types[param_index];
970 const param_ty = fn_info.param_types[param_index].toType();
989971 const param = llvm_func.getParam(llvm_arg_i);
990972 try args.ensureUnusedCapacity(1);
991973
992 if (isByRef(param_ty)) {
993 const alignment = param_ty.abiAlignment(target);
974 if (isByRef(param_ty, mod)) {
975 const alignment = param_ty.abiAlignment(mod);
994976 const param_llvm_ty = param.typeOf();
995977 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
996978 const store_inst = builder.buildStore(param, arg_ptr);
......@@ -1004,17 +986,17 @@ pub const Object = struct {
1004986 llvm_arg_i += 1;
1005987 },
1006988 .byref => {
1007 const param_ty = fn_info.param_types[it.zig_index - 1];
989 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1008990 const param_llvm_ty = try dg.lowerType(param_ty);
1009991 const param = llvm_func.getParam(llvm_arg_i);
1010 const alignment = param_ty.abiAlignment(target);
992 const alignment = param_ty.abiAlignment(mod);
1011993
1012994 dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty);
1013995 llvm_arg_i += 1;
1014996
1015997 try args.ensureUnusedCapacity(1);
1016998
1017 if (isByRef(param_ty)) {
999 if (isByRef(param_ty, mod)) {
10181000 args.appendAssumeCapacity(param);
10191001 } else {
10201002 const load_inst = builder.buildLoad(param_llvm_ty, param, "");
......@@ -1023,17 +1005,17 @@ pub const Object = struct {
10231005 }
10241006 },
10251007 .byref_mut => {
1026 const param_ty = fn_info.param_types[it.zig_index - 1];
1008 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
10271009 const param_llvm_ty = try dg.lowerType(param_ty);
10281010 const param = llvm_func.getParam(llvm_arg_i);
1029 const alignment = param_ty.abiAlignment(target);
1011 const alignment = param_ty.abiAlignment(mod);
10301012
10311013 dg.addArgAttr(llvm_func, llvm_arg_i, "noundef");
10321014 llvm_arg_i += 1;
10331015
10341016 try args.ensureUnusedCapacity(1);
10351017
1036 if (isByRef(param_ty)) {
1018 if (isByRef(param_ty, mod)) {
10371019 args.appendAssumeCapacity(param);
10381020 } else {
10391021 const load_inst = builder.buildLoad(param_llvm_ty, param, "");
......@@ -1043,15 +1025,15 @@ pub const Object = struct {
10431025 },
10441026 .abi_sized_int => {
10451027 assert(!it.byval_attr);
1046 const param_ty = fn_info.param_types[it.zig_index - 1];
1028 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
10471029 const param = llvm_func.getParam(llvm_arg_i);
10481030 llvm_arg_i += 1;
10491031
10501032 const param_llvm_ty = try dg.lowerType(param_ty);
1051 const abi_size = @intCast(c_uint, param_ty.abiSize(target));
1033 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));
10521034 const int_llvm_ty = dg.context.intType(abi_size * 8);
10531035 const alignment = @max(
1054 param_ty.abiAlignment(target),
1036 param_ty.abiAlignment(mod),
10551037 dg.object.target_data.abiAlignmentOfType(int_llvm_ty),
10561038 );
10571039 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
......@@ -1060,7 +1042,7 @@ pub const Object = struct {
10601042
10611043 try args.ensureUnusedCapacity(1);
10621044
1063 if (isByRef(param_ty)) {
1045 if (isByRef(param_ty, mod)) {
10641046 args.appendAssumeCapacity(arg_ptr);
10651047 } else {
10661048 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
......@@ -1070,15 +1052,15 @@ pub const Object = struct {
10701052 },
10711053 .slice => {
10721054 assert(!it.byval_attr);
1073 const param_ty = fn_info.param_types[it.zig_index - 1];
1074 const ptr_info = param_ty.ptrInfo().data;
1055 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
1056 const ptr_info = param_ty.ptrInfo(mod);
10751057
10761058 if (math.cast(u5, it.zig_index - 1)) |i| {
10771059 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
10781060 dg.addArgAttr(llvm_func, llvm_arg_i, "noalias");
10791061 }
10801062 }
1081 if (param_ty.zigTypeTag() != .Optional) {
1063 if (param_ty.zigTypeTag(mod) != .Optional) {
10821064 dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull");
10831065 }
10841066 if (!ptr_info.mutable) {
......@@ -1087,7 +1069,7 @@ pub const Object = struct {
10871069 if (ptr_info.@"align" != 0) {
10881070 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align");
10891071 } else {
1090 const elem_align = @max(ptr_info.pointee_type.abiAlignment(target), 1);
1072 const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1);
10911073 dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align);
10921074 }
10931075 const ptr_param = llvm_func.getParam(llvm_arg_i);
......@@ -1103,9 +1085,9 @@ pub const Object = struct {
11031085 .multiple_llvm_types => {
11041086 assert(!it.byval_attr);
11051087 const field_types = it.llvm_types_buffer[0..it.llvm_types_len];
1106 const param_ty = fn_info.param_types[it.zig_index - 1];
1088 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
11071089 const param_llvm_ty = try dg.lowerType(param_ty);
1108 const param_alignment = param_ty.abiAlignment(target);
1090 const param_alignment = param_ty.abiAlignment(mod);
11091091 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, param_alignment, target);
11101092 const llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False);
11111093 for (field_types, 0..) |_, field_i_usize| {
......@@ -1117,7 +1099,7 @@ pub const Object = struct {
11171099 store_inst.setAlignment(target.ptrBitWidth() / 8);
11181100 }
11191101
1120 const is_by_ref = isByRef(param_ty);
1102 const is_by_ref = isByRef(param_ty, mod);
11211103 const loaded = if (is_by_ref) arg_ptr else l: {
11221104 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
11231105 load_inst.setAlignment(param_alignment);
......@@ -1134,16 +1116,16 @@ pub const Object = struct {
11341116 args.appendAssumeCapacity(casted);
11351117 },
11361118 .float_array => {
1137 const param_ty = fn_info.param_types[it.zig_index - 1];
1119 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
11381120 const param_llvm_ty = try dg.lowerType(param_ty);
11391121 const param = llvm_func.getParam(llvm_arg_i);
11401122 llvm_arg_i += 1;
11411123
1142 const alignment = param_ty.abiAlignment(target);
1124 const alignment = param_ty.abiAlignment(mod);
11431125 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
11441126 _ = builder.buildStore(param, arg_ptr);
11451127
1146 if (isByRef(param_ty)) {
1128 if (isByRef(param_ty, mod)) {
11471129 try args.append(arg_ptr);
11481130 } else {
11491131 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
......@@ -1152,16 +1134,16 @@ pub const Object = struct {
11521134 }
11531135 },
11541136 .i32_array, .i64_array => {
1155 const param_ty = fn_info.param_types[it.zig_index - 1];
1137 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
11561138 const param_llvm_ty = try dg.lowerType(param_ty);
11571139 const param = llvm_func.getParam(llvm_arg_i);
11581140 llvm_arg_i += 1;
11591141
1160 const alignment = param_ty.abiAlignment(target);
1142 const alignment = param_ty.abiAlignment(mod);
11611143 const arg_ptr = buildAllocaInner(dg.context, builder, llvm_func, false, param_llvm_ty, alignment, target);
11621144 _ = builder.buildStore(param, arg_ptr);
11631145
1164 if (isByRef(param_ty)) {
1146 if (isByRef(param_ty, mod)) {
11651147 try args.append(arg_ptr);
11661148 } else {
11671149 const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, "");
......@@ -1176,27 +1158,28 @@ pub const Object = struct {
11761158 var di_scope: ?*llvm.DIScope = null;
11771159
11781160 if (dg.object.di_builder) |dib| {
1179 di_file = try dg.object.getDIFile(gpa, decl.src_namespace.file_scope);
1161 di_file = try dg.object.getDIFile(gpa, mod.namespacePtr(decl.src_namespace).file_scope);
11801162
11811163 const line_number = decl.src_line + 1;
1182 const is_internal_linkage = decl.val.tag() != .extern_fn and
1183 !module.decl_exports.contains(decl_index);
1184 const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())
1164 const is_internal_linkage = decl.val.getExternFunc(mod) == null and
1165 !mod.decl_exports.contains(decl_index);
1166 const noret_bit: c_uint = if (fn_info.return_type == .noreturn_type)
11851167 llvm.DIFlags.NoReturn
11861168 else
11871169 0;
1170 const decl_di_ty = try o.lowerDebugType(decl.ty, .full);
11881171 const subprogram = dib.createFunction(
11891172 di_file.?.toScope(),
1190 decl.name,
1173 mod.intern_pool.stringToSlice(decl.name),
11911174 llvm_func.getValueName(),
11921175 di_file.?,
11931176 line_number,
1194 try o.lowerDebugType(decl.ty, .full),
1177 decl_di_ty,
11951178 is_internal_linkage,
11961179 true, // is definition
11971180 line_number + func.lbrace_line, // scope line
11981181 llvm.DIFlags.StaticMember | noret_bit,
1199 module.comp.bin_file.options.optimize_mode != .Debug,
1182 mod.comp.bin_file.options.optimize_mode != .Debug,
12001183 null, // decl_subprogram
12011184 );
12021185 try dg.object.di_map.put(gpa, decl, subprogram.toNode());
......@@ -1219,7 +1202,7 @@ pub const Object = struct {
12191202 .func_inst_table = .{},
12201203 .llvm_func = llvm_func,
12211204 .blocks = .{},
1222 .single_threaded = module.comp.bin_file.options.single_threaded,
1205 .single_threaded = mod.comp.bin_file.options.single_threaded,
12231206 .di_scope = di_scope,
12241207 .di_file = di_file,
12251208 .base_line = dg.decl.src_line,
......@@ -1232,14 +1215,14 @@ pub const Object = struct {
12321215 fg.genBody(air.getMainBody()) catch |err| switch (err) {
12331216 error.CodegenFail => {
12341217 decl.analysis = .codegen_failure;
1235 try module.failed_decls.put(module.gpa, decl_index, dg.err_msg.?);
1218 try mod.failed_decls.put(mod.gpa, decl_index, dg.err_msg.?);
12361219 dg.err_msg = null;
12371220 return;
12381221 },
12391222 else => |e| return e,
12401223 };
12411224
1242 try o.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
1225 try o.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
12431226 }
12441227
12451228 pub fn updateDecl(self: *Object, module: *Module, decl_index: Module.Decl.Index) !void {
......@@ -1275,63 +1258,72 @@ pub const Object = struct {
12751258
12761259 pub fn updateDeclExports(
12771260 self: *Object,
1278 module: *Module,
1261 mod: *Module,
12791262 decl_index: Module.Decl.Index,
12801263 exports: []const *Module.Export,
12811264 ) !void {
1265 const gpa = mod.gpa;
12821266 // If the module does not already have the function, we ignore this function call
12831267 // because we call `updateDeclExports` at the end of `updateFunc` and `updateDecl`.
12841268 const llvm_global = self.decl_map.get(decl_index) orelse return;
1285 const decl = module.declPtr(decl_index);
1286 if (decl.isExtern()) {
1287 const is_wasm_fn = module.getTarget().isWasm() and try decl.isFunction();
1288 const mangle_name = is_wasm_fn and
1289 decl.getExternFn().?.lib_name != null and
1290 !std.mem.eql(u8, std.mem.sliceTo(decl.getExternFn().?.lib_name.?, 0), "c");
1291 const decl_name = if (mangle_name) name: {
1292 const tmp = try std.fmt.allocPrintZ(module.gpa, "{s}|{s}", .{ decl.name, decl.getExternFn().?.lib_name.? });
1293 break :name tmp.ptr;
1294 } else decl.name;
1295 defer if (mangle_name) module.gpa.free(std.mem.sliceTo(decl_name, 0));
1269 const decl = mod.declPtr(decl_index);
1270 if (decl.isExtern(mod)) {
1271 var free_decl_name = false;
1272 const decl_name = decl_name: {
1273 const decl_name = mod.intern_pool.stringToSlice(decl.name);
1274
1275 if (mod.getTarget().isWasm() and try decl.isFunction(mod)) {
1276 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
1277 if (!std.mem.eql(u8, lib_name, "c")) {
1278 free_decl_name = true;
1279 break :decl_name try std.fmt.allocPrintZ(gpa, "{s}|{s}", .{
1280 decl_name, lib_name,
1281 });
1282 }
1283 }
1284 }
1285
1286 break :decl_name decl_name;
1287 };
1288 defer if (free_decl_name) gpa.free(decl_name);
12961289
12971290 llvm_global.setValueName(decl_name);
12981291 if (self.getLlvmGlobal(decl_name)) |other_global| {
12991292 if (other_global != llvm_global) {
1300 log.debug("updateDeclExports isExtern()=true setValueName({s}) conflict", .{decl.name});
1301 try self.extern_collisions.put(module.gpa, decl_index, {});
1293 try self.extern_collisions.put(gpa, decl_index, {});
13021294 }
13031295 }
13041296 llvm_global.setUnnamedAddr(.False);
13051297 llvm_global.setLinkage(.External);
1306 if (module.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
1298 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
13071299 if (self.di_map.get(decl)) |di_node| {
1308 if (try decl.isFunction()) {
1300 if (try decl.isFunction(mod)) {
13091301 const di_func = @ptrCast(*llvm.DISubprogram, di_node);
1310 const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
1302 const linkage_name = llvm.MDString.get(self.context, decl_name.ptr, decl_name.len);
13111303 di_func.replaceLinkageName(linkage_name);
13121304 } else {
13131305 const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
1314 const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
1306 const linkage_name = llvm.MDString.get(self.context, decl_name.ptr, decl_name.len);
13151307 di_global.replaceLinkageName(linkage_name);
13161308 }
13171309 }
1318 if (decl.val.castTag(.variable)) |variable| {
1319 if (variable.data.is_threadlocal) {
1310 if (decl.val.getVariable(mod)) |variable| {
1311 if (variable.is_threadlocal) {
13201312 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
13211313 } else {
13221314 llvm_global.setThreadLocalMode(.NotThreadLocal);
13231315 }
1324 if (variable.data.is_weak_linkage) {
1316 if (variable.is_weak_linkage) {
13251317 llvm_global.setLinkage(.ExternalWeak);
13261318 }
13271319 }
13281320 } else if (exports.len != 0) {
1329 const exp_name = exports[0].options.name;
1321 const exp_name = mod.intern_pool.stringToSlice(exports[0].opts.name);
13301322 llvm_global.setValueName2(exp_name.ptr, exp_name.len);
13311323 llvm_global.setUnnamedAddr(.False);
1332 if (module.wantDllExports()) llvm_global.setDLLStorageClass(.DLLExport);
1324 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.DLLExport);
13331325 if (self.di_map.get(decl)) |di_node| {
1334 if (try decl.isFunction()) {
1326 if (try decl.isFunction(mod)) {
13351327 const di_func = @ptrCast(*llvm.DISubprogram, di_node);
13361328 const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
13371329 di_func.replaceLinkageName(linkage_name);
......@@ -1341,37 +1333,34 @@ pub const Object = struct {
13411333 di_global.replaceLinkageName(linkage_name);
13421334 }
13431335 }
1344 switch (exports[0].options.linkage) {
1336 switch (exports[0].opts.linkage) {
13451337 .Internal => unreachable,
13461338 .Strong => llvm_global.setLinkage(.External),
13471339 .Weak => llvm_global.setLinkage(.WeakODR),
13481340 .LinkOnce => llvm_global.setLinkage(.LinkOnceODR),
13491341 }
1350 switch (exports[0].options.visibility) {
1342 switch (exports[0].opts.visibility) {
13511343 .default => llvm_global.setVisibility(.Default),
13521344 .hidden => llvm_global.setVisibility(.Hidden),
13531345 .protected => llvm_global.setVisibility(.Protected),
13541346 }
1355 if (exports[0].options.section) |section| {
1356 const section_z = try module.gpa.dupeZ(u8, section);
1357 defer module.gpa.free(section_z);
1358 llvm_global.setSection(section_z);
1347 if (mod.intern_pool.stringToSliceUnwrap(exports[0].opts.section)) |section| {
1348 llvm_global.setSection(section);
13591349 }
1360 if (decl.val.castTag(.variable)) |variable| {
1361 if (variable.data.is_threadlocal) {
1350 if (decl.val.getVariable(mod)) |variable| {
1351 if (variable.is_threadlocal) {
13621352 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
13631353 }
13641354 }
13651355
13661356 // If a Decl is exported more than one time (which is rare),
13671357 // we add aliases for all but the first export.
1368 // TODO LLVM C API does not support deleting aliases. We need to
1369 // patch it to support this or figure out how to wrap the C++ API ourselves.
1358 // TODO LLVM C API does not support deleting aliases.
1359 // The planned solution to this is https://github.com/ziglang/zig/issues/13265
13701360 // Until then we iterate over existing aliases and make them point
13711361 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
13721362 for (exports[1..]) |exp| {
1373 const exp_name_z = try module.gpa.dupeZ(u8, exp.options.name);
1374 defer module.gpa.free(exp_name_z);
1363 const exp_name_z = mod.intern_pool.stringToSlice(exp.opts.name);
13751364
13761365 if (self.llvm_module.getNamedGlobalAlias(exp_name_z.ptr, exp_name_z.len)) |alias| {
13771366 alias.setAliasee(llvm_global);
......@@ -1385,15 +1374,14 @@ pub const Object = struct {
13851374 }
13861375 }
13871376 } else {
1388 const fqn = try decl.getFullyQualifiedName(module);
1389 defer module.gpa.free(fqn);
1377 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
13901378 llvm_global.setValueName2(fqn.ptr, fqn.len);
13911379 llvm_global.setLinkage(.Internal);
1392 if (module.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
1380 if (mod.wantDllExports()) llvm_global.setDLLStorageClass(.Default);
13931381 llvm_global.setUnnamedAddr(.True);
1394 if (decl.val.castTag(.variable)) |variable| {
1395 const single_threaded = module.comp.bin_file.options.single_threaded;
1396 if (variable.data.is_threadlocal and !single_threaded) {
1382 if (decl.val.getVariable(mod)) |variable| {
1383 const single_threaded = mod.comp.bin_file.options.single_threaded;
1384 if (variable.is_threadlocal and !single_threaded) {
13971385 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
13981386 } else {
13991387 llvm_global.setThreadLocalMode(.NotThreadLocal);
......@@ -1444,7 +1432,7 @@ pub const Object = struct {
14441432 const gpa = o.gpa;
14451433 // Be careful not to reference this `gop` variable after any recursive calls
14461434 // to `lowerDebugType`.
1447 const gop = try o.di_type_map.getOrPutContext(gpa, ty, .{ .mod = o.module });
1435 const gop = try o.di_type_map.getOrPut(gpa, ty.toIntern());
14481436 if (gop.found_existing) {
14491437 const annotated = gop.value_ptr.*;
14501438 const di_type = annotated.toDIType();
......@@ -1457,10 +1445,7 @@ pub const Object = struct {
14571445 };
14581446 return o.lowerDebugTypeImpl(entry, resolve, di_type);
14591447 }
1460 errdefer assert(o.di_type_map.orderedRemoveContext(ty, .{ .mod = o.module }));
1461 // The Type memory is ephemeral; since we want to store a longer-lived
1462 // reference, we need to copy it here.
1463 gop.key_ptr.* = try ty.copy(o.type_map_arena.allocator());
1448 errdefer assert(o.di_type_map.orderedRemove(ty.toIntern()));
14641449 const entry: Object.DITypeMap.Entry = .{
14651450 .key_ptr = gop.key_ptr,
14661451 .value_ptr = gop.value_ptr,
......@@ -1475,18 +1460,19 @@ pub const Object = struct {
14751460 resolve: DebugResolveStatus,
14761461 opt_fwd_decl: ?*llvm.DIType,
14771462 ) Allocator.Error!*llvm.DIType {
1478 const ty = gop.key_ptr.*;
1463 const ty = gop.key_ptr.toType();
14791464 const gpa = o.gpa;
14801465 const target = o.target;
14811466 const dib = o.di_builder.?;
1482 switch (ty.zigTypeTag()) {
1467 const mod = o.module;
1468 switch (ty.zigTypeTag(mod)) {
14831469 .Void, .NoReturn => {
14841470 const di_type = dib.createBasicType("void", 0, DW.ATE.signed);
14851471 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
14861472 return di_type;
14871473 },
14881474 .Int => {
1489 const info = ty.intInfo(target);
1475 const info = ty.intInfo(mod);
14901476 assert(info.bits != 0);
14911477 const name = try ty.nameAlloc(gpa, o.module);
14921478 defer gpa.free(name);
......@@ -1494,49 +1480,41 @@ pub const Object = struct {
14941480 .signed => DW.ATE.signed,
14951481 .unsigned => DW.ATE.unsigned,
14961482 };
1497 const di_bits = ty.abiSize(target) * 8; // lldb cannot handle non-byte sized types
1483 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
14981484 const di_type = dib.createBasicType(name, di_bits, dwarf_encoding);
14991485 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_type);
15001486 return di_type;
15011487 },
15021488 .Enum => {
1503 const owner_decl_index = ty.getOwnerDecl();
1489 const owner_decl_index = ty.getOwnerDecl(mod);
15041490 const owner_decl = o.module.declPtr(owner_decl_index);
15051491
1506 if (!ty.hasRuntimeBitsIgnoreComptime()) {
1492 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
15071493 const enum_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
15081494 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
15091495 // means we can't use `gop` anymore.
1510 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module });
1496 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
15111497 return enum_di_ty;
15121498 }
15131499
1514 const field_names = ty.enumFields().keys();
1500 const ip = &mod.intern_pool;
1501 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
15151502
1516 const enumerators = try gpa.alloc(*llvm.DIEnumerator, field_names.len);
1503 const enumerators = try gpa.alloc(*llvm.DIEnumerator, enum_type.names.len);
15171504 defer gpa.free(enumerators);
15181505
1519 var buf_field_index: Value.Payload.U32 = .{
1520 .base = .{ .tag = .enum_field_index },
1521 .data = undefined,
1522 };
1523 const field_index_val = Value.initPayload(&buf_field_index.base);
1524
1525 var buffer: Type.Payload.Bits = undefined;
1526 const int_ty = ty.intTagType(&buffer);
1527 const int_info = ty.intInfo(target);
1506 const int_ty = enum_type.tag_ty.toType();
1507 const int_info = ty.intInfo(mod);
15281508 assert(int_info.bits != 0);
15291509
1530 for (field_names, 0..) |field_name, i| {
1531 const field_name_z = try gpa.dupeZ(u8, field_name);
1532 defer gpa.free(field_name_z);
1533
1534 buf_field_index.data = @intCast(u32, i);
1535 var buf_u64: Value.Payload.U64 = undefined;
1536 const field_int_val = field_index_val.enumToInt(ty, &buf_u64);
1510 for (enum_type.names, 0..) |field_name_ip, i| {
1511 const field_name_z = ip.stringToSlice(field_name_ip);
15371512
15381513 var bigint_space: Value.BigIntSpace = undefined;
1539 const bigint = field_int_val.toBigInt(&bigint_space, target);
1514 const bigint = if (enum_type.values.len != 0)
1515 enum_type.values[i].toValue().toBigInt(&bigint_space, mod)
1516 else
1517 std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst();
15401518
15411519 if (bigint.limbs.len == 1) {
15421520 enumerators[i] = dib.createEnumerator(field_name_z, bigint.limbs[0], int_info.signedness == .unsigned);
......@@ -1555,7 +1533,7 @@ pub const Object = struct {
15551533 @panic("TODO implement bigint debug enumerators to llvm int for 32-bit compiler builds");
15561534 }
15571535
1558 const di_file = try o.getDIFile(gpa, owner_decl.src_namespace.file_scope);
1536 const di_file = try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope);
15591537 const di_scope = try o.namespaceToDebugScope(owner_decl.src_namespace);
15601538
15611539 const name = try ty.nameAlloc(gpa, o.module);
......@@ -1566,15 +1544,15 @@ pub const Object = struct {
15661544 name,
15671545 di_file,
15681546 owner_decl.src_node + 1,
1569 ty.abiSize(target) * 8,
1570 ty.abiAlignment(target) * 8,
1547 ty.abiSize(mod) * 8,
1548 ty.abiAlignment(mod) * 8,
15711549 enumerators.ptr,
15721550 @intCast(c_int, enumerators.len),
15731551 try o.lowerDebugType(int_ty, .full),
15741552 "",
15751553 );
15761554 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1577 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(enum_di_ty), .{ .mod = o.module });
1555 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(enum_di_ty));
15781556 return enum_di_ty;
15791557 },
15801558 .Float => {
......@@ -1593,49 +1571,40 @@ pub const Object = struct {
15931571 },
15941572 .Pointer => {
15951573 // Normalize everything that the debug info does not represent.
1596 const ptr_info = ty.ptrInfo().data;
1597
1598 if (ptr_info.sentinel != null or
1599 ptr_info.@"addrspace" != .generic or
1600 ptr_info.bit_offset != 0 or
1601 ptr_info.host_size != 0 or
1602 ptr_info.vector_index != .none or
1603 ptr_info.@"allowzero" or
1604 !ptr_info.mutable or
1605 ptr_info.@"volatile" or
1606 ptr_info.size == .Many or ptr_info.size == .C or
1607 !ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime())
1574 const ptr_info = Type.ptrInfoIp(&mod.intern_pool, ty.toIntern());
1575
1576 if (ptr_info.sentinel != .none or
1577 ptr_info.flags.address_space != .generic or
1578 ptr_info.packed_offset.bit_offset != 0 or
1579 ptr_info.packed_offset.host_size != 0 or
1580 ptr_info.flags.vector_index != .none or
1581 ptr_info.flags.is_allowzero or
1582 ptr_info.flags.is_const or
1583 ptr_info.flags.is_volatile or
1584 ptr_info.flags.size == .Many or ptr_info.flags.size == .C or
1585 !ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
16081586 {
1609 var payload: Type.Payload.Pointer = .{
1610 .data = .{
1611 .pointee_type = ptr_info.pointee_type,
1612 .sentinel = null,
1613 .@"align" = ptr_info.@"align",
1614 .@"addrspace" = .generic,
1615 .bit_offset = 0,
1616 .host_size = 0,
1617 .@"allowzero" = false,
1618 .mutable = true,
1619 .@"volatile" = false,
1620 .size = switch (ptr_info.size) {
1587 const bland_ptr_ty = try mod.ptrType(.{
1588 .child = if (!ptr_info.child.toType().hasRuntimeBitsIgnoreComptime(mod))
1589 .anyopaque_type
1590 else
1591 ptr_info.child,
1592 .flags = .{
1593 .alignment = ptr_info.flags.alignment,
1594 .size = switch (ptr_info.flags.size) {
16211595 .Many, .C, .One => .One,
16221596 .Slice => .Slice,
16231597 },
16241598 },
1625 };
1626 if (!ptr_info.pointee_type.hasRuntimeBitsIgnoreComptime()) {
1627 payload.data.pointee_type = Type.anyopaque;
1628 }
1629 const bland_ptr_ty = Type.initPayload(&payload.base);
1599 });
16301600 const ptr_di_ty = try o.lowerDebugType(bland_ptr_ty, resolve);
16311601 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1632 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module });
1602 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
16331603 return ptr_di_ty;
16341604 }
16351605
1636 if (ty.isSlice()) {
1637 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1638 const ptr_ty = ty.slicePtrFieldType(&buf);
1606 if (ty.isSlice(mod)) {
1607 const ptr_ty = ty.slicePtrFieldType(mod);
16391608 const len_ty = Type.usize;
16401609
16411610 const name = try ty.nameAlloc(gpa, o.module);
......@@ -1657,10 +1626,10 @@ pub const Object = struct {
16571626 break :blk fwd_decl;
16581627 };
16591628
1660 const ptr_size = ptr_ty.abiSize(target);
1661 const ptr_align = ptr_ty.abiAlignment(target);
1662 const len_size = len_ty.abiSize(target);
1663 const len_align = len_ty.abiAlignment(target);
1629 const ptr_size = ptr_ty.abiSize(mod);
1630 const ptr_align = ptr_ty.abiAlignment(mod);
1631 const len_size = len_ty.abiSize(mod);
1632 const len_align = len_ty.abiAlignment(mod);
16641633
16651634 var offset: u64 = 0;
16661635 offset += ptr_size;
......@@ -1697,8 +1666,8 @@ pub const Object = struct {
16971666 name.ptr,
16981667 di_file,
16991668 line,
1700 ty.abiSize(target) * 8, // size in bits
1701 ty.abiAlignment(target) * 8, // align in bits
1669 ty.abiSize(mod) * 8, // size in bits
1670 ty.abiAlignment(mod) * 8, // align in bits
17021671 0, // flags
17031672 null, // derived from
17041673 &fields,
......@@ -1709,65 +1678,65 @@ pub const Object = struct {
17091678 );
17101679 dib.replaceTemporary(fwd_decl, full_di_ty);
17111680 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1712 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
1681 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
17131682 return full_di_ty;
17141683 }
17151684
1716 const elem_di_ty = try o.lowerDebugType(ptr_info.pointee_type, .fwd);
1685 const elem_di_ty = try o.lowerDebugType(ptr_info.child.toType(), .fwd);
17171686 const name = try ty.nameAlloc(gpa, o.module);
17181687 defer gpa.free(name);
17191688 const ptr_di_ty = dib.createPointerType(
17201689 elem_di_ty,
17211690 target.ptrBitWidth(),
1722 ty.ptrAlignment(target) * 8,
1691 ty.ptrAlignment(mod) * 8,
17231692 name,
17241693 );
17251694 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1726 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(ptr_di_ty), .{ .mod = o.module });
1695 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(ptr_di_ty));
17271696 return ptr_di_ty;
17281697 },
17291698 .Opaque => {
1730 if (ty.tag() == .anyopaque) {
1699 if (ty.toIntern() == .anyopaque_type) {
17311700 const di_ty = dib.createBasicType("anyopaque", 0, DW.ATE.signed);
17321701 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
17331702 return di_ty;
17341703 }
17351704 const name = try ty.nameAlloc(gpa, o.module);
17361705 defer gpa.free(name);
1737 const owner_decl_index = ty.getOwnerDecl();
1706 const owner_decl_index = ty.getOwnerDecl(mod);
17381707 const owner_decl = o.module.declPtr(owner_decl_index);
17391708 const opaque_di_ty = dib.createForwardDeclType(
17401709 DW.TAG.structure_type,
17411710 name,
17421711 try o.namespaceToDebugScope(owner_decl.src_namespace),
1743 try o.getDIFile(gpa, owner_decl.src_namespace.file_scope),
1712 try o.getDIFile(gpa, mod.namespacePtr(owner_decl.src_namespace).file_scope),
17441713 owner_decl.src_node + 1,
17451714 );
17461715 // The recursive call to `lowerDebugType` va `namespaceToDebugScope`
17471716 // means we can't use `gop` anymore.
1748 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(opaque_di_ty), .{ .mod = o.module });
1717 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(opaque_di_ty));
17491718 return opaque_di_ty;
17501719 },
17511720 .Array => {
17521721 const array_di_ty = dib.createArrayType(
1753 ty.abiSize(target) * 8,
1754 ty.abiAlignment(target) * 8,
1755 try o.lowerDebugType(ty.childType(), .full),
1756 @intCast(c_int, ty.arrayLen()),
1722 ty.abiSize(mod) * 8,
1723 ty.abiAlignment(mod) * 8,
1724 try o.lowerDebugType(ty.childType(mod), .full),
1725 @intCast(c_int, ty.arrayLen(mod)),
17571726 );
17581727 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1759 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(array_di_ty), .{ .mod = o.module });
1728 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(array_di_ty));
17601729 return array_di_ty;
17611730 },
17621731 .Vector => {
1763 const elem_ty = ty.elemType2();
1732 const elem_ty = ty.elemType2(mod);
17641733 // Vector elements cannot be padded since that would make
17651734 // @bitSizOf(elem) * len > @bitSizOf(vec).
17661735 // Neither gdb nor lldb seem to be able to display non-byte sized
17671736 // vectors properly.
1768 const elem_di_type = switch (elem_ty.zigTypeTag()) {
1737 const elem_di_type = switch (elem_ty.zigTypeTag(mod)) {
17691738 .Int => blk: {
1770 const info = elem_ty.intInfo(target);
1739 const info = elem_ty.intInfo(mod);
17711740 assert(info.bits != 0);
17721741 const name = try ty.nameAlloc(gpa, o.module);
17731742 defer gpa.free(name);
......@@ -1778,34 +1747,33 @@ pub const Object = struct {
17781747 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);
17791748 },
17801749 .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean),
1781 else => try o.lowerDebugType(ty.childType(), .full),
1750 else => try o.lowerDebugType(ty.childType(mod), .full),
17821751 };
17831752
17841753 const vector_di_ty = dib.createVectorType(
1785 ty.abiSize(target) * 8,
1786 ty.abiAlignment(target) * 8,
1754 ty.abiSize(mod) * 8,
1755 ty.abiAlignment(mod) * 8,
17871756 elem_di_type,
1788 ty.vectorLen(),
1757 ty.vectorLen(mod),
17891758 );
17901759 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1791 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(vector_di_ty), .{ .mod = o.module });
1760 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(vector_di_ty));
17921761 return vector_di_ty;
17931762 },
17941763 .Optional => {
17951764 const name = try ty.nameAlloc(gpa, o.module);
17961765 defer gpa.free(name);
1797 var buf: Type.Payload.ElemType = undefined;
1798 const child_ty = ty.optionalChild(&buf);
1799 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
1766 const child_ty = ty.optionalChild(mod);
1767 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
18001768 const di_bits = 8; // lldb cannot handle non-byte sized types
18011769 const di_ty = dib.createBasicType(name, di_bits, DW.ATE.boolean);
18021770 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
18031771 return di_ty;
18041772 }
1805 if (ty.optionalReprIsPayload()) {
1773 if (ty.optionalReprIsPayload(mod)) {
18061774 const ptr_di_ty = try o.lowerDebugType(child_ty, resolve);
18071775 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1808 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.init(ptr_di_ty, resolve), .{ .mod = o.module });
1776 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.init(ptr_di_ty, resolve));
18091777 return ptr_di_ty;
18101778 }
18111779
......@@ -1826,10 +1794,10 @@ pub const Object = struct {
18261794 };
18271795
18281796 const non_null_ty = Type.u8;
1829 const payload_size = child_ty.abiSize(target);
1830 const payload_align = child_ty.abiAlignment(target);
1831 const non_null_size = non_null_ty.abiSize(target);
1832 const non_null_align = non_null_ty.abiAlignment(target);
1797 const payload_size = child_ty.abiSize(mod);
1798 const payload_align = child_ty.abiAlignment(mod);
1799 const non_null_size = non_null_ty.abiSize(mod);
1800 const non_null_align = non_null_ty.abiAlignment(mod);
18331801
18341802 var offset: u64 = 0;
18351803 offset += payload_size;
......@@ -1866,8 +1834,8 @@ pub const Object = struct {
18661834 name.ptr,
18671835 di_file,
18681836 line,
1869 ty.abiSize(target) * 8, // size in bits
1870 ty.abiAlignment(target) * 8, // align in bits
1837 ty.abiSize(mod) * 8, // size in bits
1838 ty.abiAlignment(mod) * 8, // align in bits
18711839 0, // flags
18721840 null, // derived from
18731841 &fields,
......@@ -1878,15 +1846,15 @@ pub const Object = struct {
18781846 );
18791847 dib.replaceTemporary(fwd_decl, full_di_ty);
18801848 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1881 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
1849 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
18821850 return full_di_ty;
18831851 },
18841852 .ErrorUnion => {
1885 const payload_ty = ty.errorUnionPayload();
1886 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1853 const payload_ty = ty.errorUnionPayload(mod);
1854 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
18871855 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
18881856 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1889 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(err_set_di_ty), .{ .mod = o.module });
1857 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty));
18901858 return err_set_di_ty;
18911859 }
18921860 const name = try ty.nameAlloc(gpa, o.module);
......@@ -1907,10 +1875,10 @@ pub const Object = struct {
19071875 break :blk fwd_decl;
19081876 };
19091877
1910 const error_size = Type.anyerror.abiSize(target);
1911 const error_align = Type.anyerror.abiAlignment(target);
1912 const payload_size = payload_ty.abiSize(target);
1913 const payload_align = payload_ty.abiAlignment(target);
1878 const error_size = Type.anyerror.abiSize(mod);
1879 const error_align = Type.anyerror.abiAlignment(mod);
1880 const payload_size = payload_ty.abiSize(mod);
1881 const payload_align = payload_ty.abiAlignment(mod);
19141882
19151883 var error_index: u32 = undefined;
19161884 var payload_index: u32 = undefined;
......@@ -1957,8 +1925,8 @@ pub const Object = struct {
19571925 name.ptr,
19581926 di_file,
19591927 line,
1960 ty.abiSize(target) * 8, // size in bits
1961 ty.abiAlignment(target) * 8, // align in bits
1928 ty.abiSize(mod) * 8, // size in bits
1929 ty.abiAlignment(mod) * 8, // align in bits
19621930 0, // flags
19631931 null, // derived from
19641932 &fields,
......@@ -1969,7 +1937,7 @@ pub const Object = struct {
19691937 );
19701938 dib.replaceTemporary(fwd_decl, full_di_ty);
19711939 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
1972 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
1940 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
19731941 return full_di_ty;
19741942 },
19751943 .ErrorSet => {
......@@ -1984,16 +1952,15 @@ pub const Object = struct {
19841952 const name = try ty.nameAlloc(gpa, o.module);
19851953 defer gpa.free(name);
19861954
1987 if (ty.castTag(.@"struct")) |payload| {
1988 const struct_obj = payload.data;
1955 if (mod.typeToStruct(ty)) |struct_obj| {
19891956 if (struct_obj.layout == .Packed and struct_obj.haveFieldTypes()) {
19901957 assert(struct_obj.haveLayout());
1991 const info = struct_obj.backing_int_ty.intInfo(target);
1958 const info = struct_obj.backing_int_ty.intInfo(mod);
19921959 const dwarf_encoding: c_uint = switch (info.signedness) {
19931960 .signed => DW.ATE.signed,
19941961 .unsigned => DW.ATE.unsigned,
19951962 };
1996 const di_bits = ty.abiSize(target) * 8; // lldb cannot handle non-byte sized types
1963 const di_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types
19971964 const di_ty = dib.createBasicType(name, di_bits, dwarf_encoding);
19981965 gop.value_ptr.* = AnnotatedDITypePtr.initFull(di_ty);
19991966 return di_ty;
......@@ -2013,98 +1980,98 @@ pub const Object = struct {
20131980 break :blk fwd_decl;
20141981 };
20151982
2016 if (ty.isSimpleTupleOrAnonStruct()) {
2017 const tuple = ty.tupleFields();
2018
2019 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
2020 defer di_fields.deinit(gpa);
2021
2022 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
2023
2024 comptime assert(struct_layout_version == 2);
2025 var offset: u64 = 0;
2026
2027 for (tuple.types, 0..) |field_ty, i| {
2028 const field_val = tuple.values[i];
2029 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
2030
2031 const field_size = field_ty.abiSize(target);
2032 const field_align = field_ty.abiAlignment(target);
2033 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2034 offset = field_offset + field_size;
2035
2036 const field_name = if (ty.castTag(.anon_struct)) |payload|
2037 try gpa.dupeZ(u8, payload.data.names[i])
2038 else
2039 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2040 defer gpa.free(field_name);
1983 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1984 .anon_struct_type => |tuple| {
1985 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
1986 defer di_fields.deinit(gpa);
1987
1988 try di_fields.ensureUnusedCapacity(gpa, tuple.types.len);
1989
1990 comptime assert(struct_layout_version == 2);
1991 var offset: u64 = 0;
1992
1993 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
1994 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1995
1996 const field_size = field_ty.toType().abiSize(mod);
1997 const field_align = field_ty.toType().abiAlignment(mod);
1998 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1999 offset = field_offset + field_size;
2000
2001 const field_name = if (tuple.names.len != 0)
2002 mod.intern_pool.stringToSlice(tuple.names[i])
2003 else
2004 try std.fmt.allocPrintZ(gpa, "{d}", .{i});
2005 defer if (tuple.names.len == 0) gpa.free(field_name);
2006
2007 try di_fields.append(gpa, dib.createMemberType(
2008 fwd_decl.toScope(),
2009 field_name,
2010 null, // file
2011 0, // line
2012 field_size * 8, // size in bits
2013 field_align * 8, // align in bits
2014 field_offset * 8, // offset in bits
2015 0, // flags
2016 try o.lowerDebugType(field_ty.toType(), .full),
2017 ));
2018 }
20412019
2042 try di_fields.append(gpa, dib.createMemberType(
2043 fwd_decl.toScope(),
2044 field_name,
2020 const full_di_ty = dib.createStructType(
2021 compile_unit_scope,
2022 name.ptr,
20452023 null, // file
20462024 0, // line
2047 field_size * 8, // size in bits
2048 field_align * 8, // align in bits
2049 field_offset * 8, // offset in bits
2025 ty.abiSize(mod) * 8, // size in bits
2026 ty.abiAlignment(mod) * 8, // align in bits
20502027 0, // flags
2051 try o.lowerDebugType(field_ty, .full),
2052 ));
2053 }
2054
2055 const full_di_ty = dib.createStructType(
2056 compile_unit_scope,
2057 name.ptr,
2058 null, // file
2059 0, // line
2060 ty.abiSize(target) * 8, // size in bits
2061 ty.abiAlignment(target) * 8, // align in bits
2062 0, // flags
2063 null, // derived from
2064 di_fields.items.ptr,
2065 @intCast(c_int, di_fields.items.len),
2066 0, // run time lang
2067 null, // vtable holder
2068 "", // unique id
2069 );
2070 dib.replaceTemporary(fwd_decl, full_di_ty);
2071 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2072 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2073 return full_di_ty;
2074 }
2075
2076 if (ty.castTag(.@"struct")) |payload| {
2077 const struct_obj = payload.data;
2078 if (!struct_obj.haveFieldTypes()) {
2079 // This can happen if a struct type makes it all the way to
2080 // flush() without ever being instantiated or referenced (even
2081 // via pointer). The only reason we are hearing about it now is
2082 // that it is being used as a namespace to put other debug types
2083 // into. Therefore we can satisfy this by making an empty namespace,
2084 // rather than changing the frontend to unnecessarily resolve the
2085 // struct field types.
2086 const owner_decl_index = ty.getOwnerDecl();
2087 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2088 dib.replaceTemporary(fwd_decl, struct_di_ty);
2089 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2090 // means we can't use `gop` anymore.
2091 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
2092 return struct_di_ty;
2093 }
2028 null, // derived from
2029 di_fields.items.ptr,
2030 @intCast(c_int, di_fields.items.len),
2031 0, // run time lang
2032 null, // vtable holder
2033 "", // unique id
2034 );
2035 dib.replaceTemporary(fwd_decl, full_di_ty);
2036 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2037 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
2038 return full_di_ty;
2039 },
2040 .struct_type => |struct_type| s: {
2041 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
2042
2043 if (!struct_obj.haveFieldTypes()) {
2044 // This can happen if a struct type makes it all the way to
2045 // flush() without ever being instantiated or referenced (even
2046 // via pointer). The only reason we are hearing about it now is
2047 // that it is being used as a namespace to put other debug types
2048 // into. Therefore we can satisfy this by making an empty namespace,
2049 // rather than changing the frontend to unnecessarily resolve the
2050 // struct field types.
2051 const owner_decl_index = ty.getOwnerDecl(mod);
2052 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
2053 dib.replaceTemporary(fwd_decl, struct_di_ty);
2054 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
2055 // means we can't use `gop` anymore.
2056 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
2057 return struct_di_ty;
2058 }
2059 },
2060 else => {},
20942061 }
20952062
2096 if (!ty.hasRuntimeBitsIgnoreComptime()) {
2097 const owner_decl_index = ty.getOwnerDecl();
2063 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
2064 const owner_decl_index = ty.getOwnerDecl(mod);
20982065 const struct_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
20992066 dib.replaceTemporary(fwd_decl, struct_di_ty);
21002067 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
21012068 // means we can't use `gop` anymore.
2102 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(struct_di_ty), .{ .mod = o.module });
2069 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(struct_di_ty));
21032070 return struct_di_ty;
21042071 }
21052072
2106 const fields = ty.structFields();
2107 const layout = ty.containerLayout();
2073 const fields = ty.structFields(mod);
2074 const layout = ty.containerLayout(mod);
21082075
21092076 var di_fields: std.ArrayListUnmanaged(*llvm.DIType) = .{};
21102077 defer di_fields.deinit(gpa);
......@@ -2114,16 +2081,15 @@ pub const Object = struct {
21142081 comptime assert(struct_layout_version == 2);
21152082 var offset: u64 = 0;
21162083
2117 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator();
2084 var it = mod.typeToStruct(ty).?.runtimeFieldIterator(mod);
21182085 while (it.next()) |field_and_index| {
21192086 const field = field_and_index.field;
2120 const field_size = field.ty.abiSize(target);
2121 const field_align = field.alignment(target, layout);
2087 const field_size = field.ty.abiSize(mod);
2088 const field_align = field.alignment(mod, layout);
21222089 const field_offset = std.mem.alignForwardGeneric(u64, offset, field_align);
21232090 offset = field_offset + field_size;
21242091
2125 const field_name = try gpa.dupeZ(u8, fields.keys()[field_and_index.index]);
2126 defer gpa.free(field_name);
2092 const field_name = mod.intern_pool.stringToSlice(fields.keys()[field_and_index.index]);
21272093
21282094 try di_fields.append(gpa, dib.createMemberType(
21292095 fwd_decl.toScope(),
......@@ -2143,8 +2109,8 @@ pub const Object = struct {
21432109 name.ptr,
21442110 null, // file
21452111 0, // line
2146 ty.abiSize(target) * 8, // size in bits
2147 ty.abiAlignment(target) * 8, // align in bits
2112 ty.abiSize(mod) * 8, // size in bits
2113 ty.abiAlignment(mod) * 8, // align in bits
21482114 0, // flags
21492115 null, // derived from
21502116 di_fields.items.ptr,
......@@ -2155,12 +2121,12 @@ pub const Object = struct {
21552121 );
21562122 dib.replaceTemporary(fwd_decl, full_di_ty);
21572123 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2158 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2124 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
21592125 return full_di_ty;
21602126 },
21612127 .Union => {
21622128 const compile_unit_scope = o.di_compile_unit.?.toScope();
2163 const owner_decl_index = ty.getOwnerDecl();
2129 const owner_decl_index = ty.getOwnerDecl(mod);
21642130
21652131 const name = try ty.nameAlloc(gpa, o.module);
21662132 defer gpa.free(name);
......@@ -2178,17 +2144,17 @@ pub const Object = struct {
21782144 break :blk fwd_decl;
21792145 };
21802146
2181 const union_obj = ty.cast(Type.Payload.Union).?.data;
2182 if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime()) {
2147 const union_obj = mod.typeToUnion(ty).?;
2148 if (!union_obj.haveFieldTypes() or !ty.hasRuntimeBitsIgnoreComptime(mod)) {
21832149 const union_di_ty = try o.makeEmptyNamespaceDIType(owner_decl_index);
21842150 dib.replaceTemporary(fwd_decl, union_di_ty);
21852151 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
21862152 // means we can't use `gop` anymore.
2187 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module });
2153 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
21882154 return union_di_ty;
21892155 }
21902156
2191 const layout = ty.unionGetLayout(target);
2157 const layout = ty.unionGetLayout(mod);
21922158
21932159 if (layout.payload_size == 0) {
21942160 const tag_di_ty = try o.lowerDebugType(union_obj.tag_ty, .full);
......@@ -2198,8 +2164,8 @@ pub const Object = struct {
21982164 name.ptr,
21992165 null, // file
22002166 0, // line
2201 ty.abiSize(target) * 8, // size in bits
2202 ty.abiAlignment(target) * 8, // align in bits
2167 ty.abiSize(mod) * 8, // size in bits
2168 ty.abiAlignment(mod) * 8, // align in bits
22032169 0, // flags
22042170 null, // derived from
22052171 &di_fields,
......@@ -2211,7 +2177,7 @@ pub const Object = struct {
22112177 dib.replaceTemporary(fwd_decl, full_di_ty);
22122178 // The recursive call to `lowerDebugType` via `makeEmptyNamespaceDIType`
22132179 // means we can't use `gop` anymore.
2214 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2180 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
22152181 return full_di_ty;
22162182 }
22172183
......@@ -2225,24 +2191,22 @@ pub const Object = struct {
22252191 const field_name = kv.key_ptr.*;
22262192 const field = kv.value_ptr.*;
22272193
2228 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
2229
2230 const field_size = field.ty.abiSize(target);
2231 const field_align = field.normalAlignment(target);
2194 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
22322195
2233 const field_name_copy = try gpa.dupeZ(u8, field_name);
2234 defer gpa.free(field_name_copy);
2196 const field_size = field.ty.abiSize(mod);
2197 const field_align = field.normalAlignment(mod);
22352198
2199 const field_di_ty = try o.lowerDebugType(field.ty, .full);
22362200 di_fields.appendAssumeCapacity(dib.createMemberType(
22372201 fwd_decl.toScope(),
2238 field_name_copy,
2202 mod.intern_pool.stringToSlice(field_name),
22392203 null, // file
22402204 0, // line
22412205 field_size * 8, // size in bits
22422206 field_align * 8, // align in bits
22432207 0, // offset in bits
22442208 0, // flags
2245 try o.lowerDebugType(field.ty, .full),
2209 field_di_ty,
22462210 ));
22472211 }
22482212
......@@ -2258,8 +2222,8 @@ pub const Object = struct {
22582222 union_name.ptr,
22592223 null, // file
22602224 0, // line
2261 ty.abiSize(target) * 8, // size in bits
2262 ty.abiAlignment(target) * 8, // align in bits
2225 ty.abiSize(mod) * 8, // size in bits
2226 ty.abiAlignment(mod) * 8, // align in bits
22632227 0, // flags
22642228 di_fields.items.ptr,
22652229 @intCast(c_int, di_fields.items.len),
......@@ -2270,7 +2234,7 @@ pub const Object = struct {
22702234 if (layout.tag_size == 0) {
22712235 dib.replaceTemporary(fwd_decl, union_di_ty);
22722236 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2273 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(union_di_ty), .{ .mod = o.module });
2237 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(union_di_ty));
22742238 return union_di_ty;
22752239 }
22762240
......@@ -2319,8 +2283,8 @@ pub const Object = struct {
23192283 name.ptr,
23202284 null, // file
23212285 0, // line
2322 ty.abiSize(target) * 8, // size in bits
2323 ty.abiAlignment(target) * 8, // align in bits
2286 ty.abiSize(mod) * 8, // size in bits
2287 ty.abiAlignment(mod) * 8, // align in bits
23242288 0, // flags
23252289 null, // derived from
23262290 &full_di_fields,
......@@ -2331,53 +2295,42 @@ pub const Object = struct {
23312295 );
23322296 dib.replaceTemporary(fwd_decl, full_di_ty);
23332297 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2334 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(full_di_ty), .{ .mod = o.module });
2298 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(full_di_ty));
23352299 return full_di_ty;
23362300 },
23372301 .Fn => {
2338 const fn_info = ty.fnInfo();
2302 const fn_info = mod.typeToFunc(ty).?;
23392303
23402304 var param_di_types = std.ArrayList(*llvm.DIType).init(gpa);
23412305 defer param_di_types.deinit();
23422306
23432307 // Return type goes first.
2344 if (fn_info.return_type.hasRuntimeBitsIgnoreComptime()) {
2345 const sret = firstParamSRet(fn_info, target);
2346 const di_ret_ty = if (sret) Type.void else fn_info.return_type;
2308 if (fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
2309 const sret = firstParamSRet(fn_info, mod);
2310 const di_ret_ty = if (sret) Type.void else fn_info.return_type.toType();
23472311 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));
23482312
23492313 if (sret) {
2350 var ptr_ty_payload: Type.Payload.ElemType = .{
2351 .base = .{ .tag = .single_mut_pointer },
2352 .data = fn_info.return_type,
2353 };
2354 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2314 const ptr_ty = try mod.singleMutPtrType(fn_info.return_type.toType());
23552315 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23562316 }
23572317 } else {
23582318 try param_di_types.append(try o.lowerDebugType(Type.void, .full));
23592319 }
23602320
2361 if (fn_info.return_type.isError() and
2321 if (fn_info.return_type.toType().isError(mod) and
23622322 o.module.comp.bin_file.options.error_return_tracing)
23632323 {
2364 var ptr_ty_payload: Type.Payload.ElemType = .{
2365 .base = .{ .tag = .single_mut_pointer },
2366 .data = o.getStackTraceType(),
2367 };
2368 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2324 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
23692325 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23702326 }
23712327
2372 for (fn_info.param_types) |param_ty| {
2373 if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue;
2328 for (0..mod.typeToFunc(ty).?.param_types.len) |i| {
2329 const param_ty = mod.typeToFunc(ty).?.param_types[i].toType();
2330 if (!param_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
23742331
2375 if (isByRef(param_ty)) {
2376 var ptr_ty_payload: Type.Payload.ElemType = .{
2377 .base = .{ .tag = .single_mut_pointer },
2378 .data = param_ty,
2379 };
2380 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
2332 if (isByRef(param_ty, mod)) {
2333 const ptr_ty = try mod.singleMutPtrType(param_ty);
23812334 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
23822335 } else {
23832336 try param_di_types.append(try o.lowerDebugType(param_ty, .full));
......@@ -2390,7 +2343,7 @@ pub const Object = struct {
23902343 0,
23912344 );
23922345 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
2393 try o.di_type_map.putContext(gpa, ty, AnnotatedDITypePtr.initFull(fn_di_ty), .{ .mod = o.module });
2346 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(fn_di_ty));
23942347 return fn_di_ty;
23952348 },
23962349 .ComptimeInt => unreachable,
......@@ -2405,8 +2358,10 @@ pub const Object = struct {
24052358 }
24062359 }
24072360
2408 fn namespaceToDebugScope(o: *Object, namespace: *const Module.Namespace) !*llvm.DIScope {
2409 if (namespace.parent == null) {
2361 fn namespaceToDebugScope(o: *Object, namespace_index: Module.Namespace.Index) !*llvm.DIScope {
2362 const mod = o.module;
2363 const namespace = mod.namespacePtr(namespace_index);
2364 if (namespace.parent == .none) {
24102365 const di_file = try o.getDIFile(o.gpa, namespace.file_scope);
24112366 return di_file.toScope();
24122367 }
......@@ -2418,12 +2373,14 @@ pub const Object = struct {
24182373 /// Assertion `!isa<DIType>(Scope) && "shouldn't make a namespace scope for a type"'
24192374 /// when targeting CodeView (Windows).
24202375 fn makeEmptyNamespaceDIType(o: *Object, decl_index: Module.Decl.Index) !*llvm.DIType {
2421 const decl = o.module.declPtr(decl_index);
2376 const mod = o.module;
2377 const decl = mod.declPtr(decl_index);
24222378 const fields: [0]*llvm.DIType = .{};
2379 const di_scope = try o.namespaceToDebugScope(decl.src_namespace);
24232380 return o.di_builder.?.createStructType(
2424 try o.namespaceToDebugScope(decl.src_namespace),
2425 decl.name, // TODO use fully qualified name
2426 try o.getDIFile(o.gpa, decl.src_namespace.file_scope),
2381 di_scope,
2382 mod.intern_pool.stringToSlice(decl.name), // TODO use fully qualified name
2383 try o.getDIFile(o.gpa, mod.namespacePtr(decl.src_namespace).file_scope),
24272384 decl.src_line + 1,
24282385 0, // size in bits
24292386 0, // align in bits
......@@ -2437,28 +2394,28 @@ pub const Object = struct {
24372394 );
24382395 }
24392396
2440 fn getStackTraceType(o: *Object) Type {
2397 fn getStackTraceType(o: *Object) Allocator.Error!Type {
24412398 const mod = o.module;
24422399
24432400 const std_pkg = mod.main_pkg.table.get("std").?;
24442401 const std_file = (mod.importPkg(std_pkg) catch unreachable).file;
24452402
2446 const builtin_str: []const u8 = "builtin";
2447 const std_namespace = mod.declPtr(std_file.root_decl.unwrap().?).src_namespace;
2403 const builtin_str = try mod.intern_pool.getOrPutString(mod.gpa, "builtin");
2404 const std_namespace = mod.namespacePtr(mod.declPtr(std_file.root_decl.unwrap().?).src_namespace);
24482405 const builtin_decl = std_namespace.decls
24492406 .getKeyAdapted(builtin_str, Module.DeclAdapter{ .mod = mod }).?;
24502407
2451 const stack_trace_str: []const u8 = "StackTrace";
2408 const stack_trace_str = try mod.intern_pool.getOrPutString(mod.gpa, "StackTrace");
24522409 // buffer is only used for int_type, `builtin` is a struct.
2453 const builtin_ty = mod.declPtr(builtin_decl).val.toType(undefined);
2454 const builtin_namespace = builtin_ty.getNamespace().?;
2410 const builtin_ty = mod.declPtr(builtin_decl).val.toType();
2411 const builtin_namespace = builtin_ty.getNamespace(mod).?;
24552412 const stack_trace_decl_index = builtin_namespace.decls
24562413 .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?;
24572414 const stack_trace_decl = mod.declPtr(stack_trace_decl_index);
24582415
24592416 // Sema should have ensured that StackTrace was analyzed.
24602417 assert(stack_trace_decl.has_tv);
2461 return stack_trace_decl.val.toType(undefined);
2418 return stack_trace_decl.val.toType();
24622419 }
24632420};
24642421
......@@ -2474,7 +2431,8 @@ pub const DeclGen = struct {
24742431 fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
24752432 @setCold(true);
24762433 assert(self.err_msg == null);
2477 const src_loc = LazySrcLoc.nodeOffset(0).toSrcLoc(self.decl);
2434 const mod = self.module;
2435 const src_loc = LazySrcLoc.nodeOffset(0).toSrcLoc(self.decl, mod);
24782436 self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args);
24792437 return error.CodegenFail;
24802438 }
......@@ -2484,31 +2442,27 @@ pub const DeclGen = struct {
24842442 }
24852443
24862444 fn genDecl(dg: *DeclGen) !void {
2445 const mod = dg.module;
24872446 const decl = dg.decl;
24882447 const decl_index = dg.decl_index;
24892448 assert(decl.has_tv);
24902449
2491 log.debug("gen: {s} type: {}, value: {}", .{
2492 decl.name, decl.ty.fmtDebug(), decl.val.fmtDebug(),
2493 });
2494 assert(decl.val.tag() != .function);
2495 if (decl.val.castTag(.extern_fn)) |extern_fn| {
2496 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
2450 if (decl.val.getExternFunc(mod)) |extern_func| {
2451 _ = try dg.resolveLlvmFunction(extern_func.decl);
24972452 } else {
2498 const target = dg.module.getTarget();
2453 const target = mod.getTarget();
24992454 var global = try dg.resolveGlobalDecl(decl_index);
2500 global.setAlignment(decl.getAlignment(target));
2501 if (decl.@"linksection") |section| global.setSection(section);
2455 global.setAlignment(decl.getAlignment(mod));
2456 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| global.setSection(s);
25022457 assert(decl.has_tv);
2503 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
2504 const variable = payload.data;
2458 const init_val = if (decl.val.getVariable(mod)) |variable| init_val: {
25052459 break :init_val variable.init;
25062460 } else init_val: {
25072461 global.setGlobalConstant(.True);
2508 break :init_val decl.val;
2462 break :init_val decl.val.toIntern();
25092463 };
2510 if (init_val.tag() != .unreachable_value) {
2511 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val });
2464 if (init_val != .none) {
2465 const llvm_init = try dg.lowerValue(.{ .ty = decl.ty, .val = init_val.toValue() });
25122466 if (global.globalGetValueType() == llvm_init.typeOf()) {
25132467 global.setInitializer(llvm_init);
25142468 } else {
......@@ -2533,7 +2487,8 @@ pub const DeclGen = struct {
25332487 new_global.setLinkage(global.getLinkage());
25342488 new_global.setUnnamedAddr(global.getUnnamedAddress());
25352489 new_global.setAlignment(global.getAlignment());
2536 if (decl.@"linksection") |section| new_global.setSection(section);
2490 if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s|
2491 new_global.setSection(s);
25372492 new_global.setInitializer(llvm_init);
25382493 // TODO: How should this work then the address space of a global changed?
25392494 global.replaceAllUsesWith(new_global);
......@@ -2545,13 +2500,13 @@ pub const DeclGen = struct {
25452500 }
25462501
25472502 if (dg.object.di_builder) |dib| {
2548 const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);
2503 const di_file = try dg.object.getDIFile(dg.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
25492504
25502505 const line_number = decl.src_line + 1;
25512506 const is_internal_linkage = !dg.module.decl_exports.contains(decl_index);
25522507 const di_global = dib.createGlobalVariableExpression(
25532508 di_file.toScope(),
2554 decl.name,
2509 mod.intern_pool.stringToSlice(decl.name),
25552510 global.getValueName(),
25562511 di_file,
25572512 line_number,
......@@ -2560,7 +2515,7 @@ pub const DeclGen = struct {
25602515 );
25612516
25622517 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.getVariable().toNode());
2563 if (!is_internal_linkage or decl.isExtern()) global.attachMetaData(di_global);
2518 if (!is_internal_linkage or decl.isExtern(mod)) global.attachMetaData(di_global);
25642519 }
25652520 }
25662521 }
......@@ -2569,36 +2524,35 @@ pub const DeclGen = struct {
25692524 /// Note that this can be called before the function's semantic analysis has
25702525 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
25712526 fn resolveLlvmFunction(dg: *DeclGen, decl_index: Module.Decl.Index) !*llvm.Value {
2572 const decl = dg.module.declPtr(decl_index);
2527 const mod = dg.module;
2528 const decl = mod.declPtr(decl_index);
25732529 const zig_fn_type = decl.ty;
25742530 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl_index);
25752531 if (gop.found_existing) return gop.value_ptr.*;
25762532
25772533 assert(decl.has_tv);
2578 const fn_info = zig_fn_type.fnInfo();
2579 const target = dg.module.getTarget();
2580 const sret = firstParamSRet(fn_info, target);
2534 const fn_info = mod.typeToFunc(zig_fn_type).?;
2535 const target = mod.getTarget();
2536 const sret = firstParamSRet(fn_info, mod);
25812537
25822538 const fn_type = try dg.lowerType(zig_fn_type);
25832539
2584 const fqn = try decl.getFullyQualifiedName(dg.module);
2585 defer dg.gpa.free(fqn);
2540 const fqn = try decl.getFullyQualifiedName(mod);
25862541
25872542 const llvm_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
2588 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(fqn, fn_type, llvm_addrspace);
2543 const llvm_fn = dg.llvmModule().addFunctionInAddressSpace(mod.intern_pool.stringToSlice(fqn), fn_type, llvm_addrspace);
25892544 gop.value_ptr.* = llvm_fn;
25902545
2591 const is_extern = decl.isExtern();
2546 const is_extern = decl.isExtern(mod);
25922547 if (!is_extern) {
25932548 llvm_fn.setLinkage(.Internal);
25942549 llvm_fn.setUnnamedAddr(.True);
25952550 } else {
2596 if (dg.module.getTarget().isWasm()) {
2597 dg.addFnAttrString(llvm_fn, "wasm-import-name", std.mem.sliceTo(decl.name, 0));
2598 if (decl.getExternFn().?.lib_name) |lib_name| {
2599 const module_name = std.mem.sliceTo(lib_name, 0);
2600 if (!std.mem.eql(u8, module_name, "c")) {
2601 dg.addFnAttrString(llvm_fn, "wasm-import-module", module_name);
2551 if (target.isWasm()) {
2552 dg.addFnAttrString(llvm_fn, "wasm-import-name", mod.intern_pool.stringToSlice(decl.name));
2553 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
2554 if (!std.mem.eql(u8, lib_name, "c")) {
2555 dg.addFnAttrString(llvm_fn, "wasm-import-module", lib_name);
26022556 }
26032557 }
26042558 }
......@@ -2608,12 +2562,12 @@ pub const DeclGen = struct {
26082562 dg.addArgAttr(llvm_fn, 0, "nonnull"); // Sret pointers must not be address 0
26092563 dg.addArgAttr(llvm_fn, 0, "noalias");
26102564
2611 const raw_llvm_ret_ty = try dg.lowerType(fn_info.return_type);
2565 const raw_llvm_ret_ty = try dg.lowerType(fn_info.return_type.toType());
26122566 llvm_fn.addSretAttr(raw_llvm_ret_ty);
26132567 }
26142568
2615 const err_return_tracing = fn_info.return_type.isError() and
2616 dg.module.comp.bin_file.options.error_return_tracing;
2569 const err_return_tracing = fn_info.return_type.toType().isError(mod) and
2570 mod.comp.bin_file.options.error_return_tracing;
26172571
26182572 if (err_return_tracing) {
26192573 dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull");
......@@ -2635,14 +2589,14 @@ pub const DeclGen = struct {
26352589 },
26362590 }
26372591
2638 if (fn_info.alignment != 0) {
2639 llvm_fn.setAlignment(fn_info.alignment);
2592 if (fn_info.alignment.toByteUnitsOptional()) |a| {
2593 llvm_fn.setAlignment(@intCast(c_uint, a));
26402594 }
26412595
26422596 // Function attributes that are independent of analysis results of the function body.
26432597 dg.addCommonFnAttributes(llvm_fn);
26442598
2645 if (fn_info.return_type.isNoReturn()) {
2599 if (fn_info.return_type == .noreturn_type) {
26462600 dg.addFnAttr(llvm_fn, "noreturn");
26472601 }
26482602
......@@ -2655,15 +2609,15 @@ pub const DeclGen = struct {
26552609 while (it.next()) |lowering| switch (lowering) {
26562610 .byval => {
26572611 const param_index = it.zig_index - 1;
2658 const param_ty = fn_info.param_types[param_index];
2659 if (!isByRef(param_ty)) {
2612 const param_ty = fn_info.param_types[param_index].toType();
2613 if (!isByRef(param_ty, mod)) {
26602614 dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1);
26612615 }
26622616 },
26632617 .byref => {
26642618 const param_ty = fn_info.param_types[it.zig_index - 1];
2665 const param_llvm_ty = try dg.lowerType(param_ty);
2666 const alignment = param_ty.abiAlignment(target);
2619 const param_llvm_ty = try dg.lowerType(param_ty.toType());
2620 const alignment = param_ty.toType().abiAlignment(mod);
26672621 dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
26682622 },
26692623 .byref_mut => {
......@@ -2735,35 +2689,35 @@ pub const DeclGen = struct {
27352689 if (gop.found_existing) return gop.value_ptr.*;
27362690 errdefer assert(dg.object.decl_map.remove(decl_index));
27372691
2738 const decl = dg.module.declPtr(decl_index);
2739 const fqn = try decl.getFullyQualifiedName(dg.module);
2740 defer dg.gpa.free(fqn);
2692 const mod = dg.module;
2693 const decl = mod.declPtr(decl_index);
2694 const fqn = try decl.getFullyQualifiedName(mod);
27412695
2742 const target = dg.module.getTarget();
2696 const target = mod.getTarget();
27432697
27442698 const llvm_type = try dg.lowerType(decl.ty);
27452699 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
27462700
27472701 const llvm_global = dg.object.llvm_module.addGlobalInAddressSpace(
27482702 llvm_type,
2749 fqn,
2703 mod.intern_pool.stringToSlice(fqn),
27502704 llvm_actual_addrspace,
27512705 );
27522706 gop.value_ptr.* = llvm_global;
27532707
27542708 // This is needed for declarations created by `@extern`.
2755 if (decl.isExtern()) {
2756 llvm_global.setValueName(decl.name);
2709 if (decl.isExtern(mod)) {
2710 llvm_global.setValueName(mod.intern_pool.stringToSlice(decl.name));
27572711 llvm_global.setUnnamedAddr(.False);
27582712 llvm_global.setLinkage(.External);
2759 if (decl.val.castTag(.variable)) |variable| {
2760 const single_threaded = dg.module.comp.bin_file.options.single_threaded;
2761 if (variable.data.is_threadlocal and !single_threaded) {
2713 if (decl.val.getVariable(mod)) |variable| {
2714 const single_threaded = mod.comp.bin_file.options.single_threaded;
2715 if (variable.is_threadlocal and !single_threaded) {
27622716 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
27632717 } else {
27642718 llvm_global.setThreadLocalMode(.NotThreadLocal);
27652719 }
2766 if (variable.data.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
2720 if (variable.is_weak_linkage) llvm_global.setLinkage(.ExternalWeak);
27672721 }
27682722 } else {
27692723 llvm_global.setLinkage(.Internal);
......@@ -2784,12 +2738,13 @@ pub const DeclGen = struct {
27842738
27852739 fn lowerType(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type {
27862740 const llvm_ty = try lowerTypeInner(dg, t);
2741 const mod = dg.module;
27872742 if (std.debug.runtime_safety and false) check: {
2788 if (t.zigTypeTag() == .Opaque) break :check;
2789 if (!t.hasRuntimeBits()) break :check;
2743 if (t.zigTypeTag(mod) == .Opaque) break :check;
2744 if (!t.hasRuntimeBits(mod)) break :check;
27902745 if (!llvm_ty.isSized().toBool()) break :check;
27912746
2792 const zig_size = t.abiSize(dg.module.getTarget());
2747 const zig_size = t.abiSize(mod);
27932748 const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty);
27942749 if (llvm_size != zig_size) {
27952750 log.err("when lowering {}, Zig ABI size = {d} but LLVM ABI size = {d}", .{
......@@ -2802,18 +2757,18 @@ pub const DeclGen = struct {
28022757
28032758 fn lowerTypeInner(dg: *DeclGen, t: Type) Allocator.Error!*llvm.Type {
28042759 const gpa = dg.gpa;
2805 const target = dg.module.getTarget();
2806 switch (t.zigTypeTag()) {
2760 const mod = dg.module;
2761 const target = mod.getTarget();
2762 switch (t.zigTypeTag(mod)) {
28072763 .Void, .NoReturn => return dg.context.voidType(),
28082764 .Int => {
2809 const info = t.intInfo(target);
2765 const info = t.intInfo(mod);
28102766 assert(info.bits != 0);
28112767 return dg.context.intType(info.bits);
28122768 },
28132769 .Enum => {
2814 var buffer: Type.Payload.Bits = undefined;
2815 const int_ty = t.intTagType(&buffer);
2816 const bit_count = int_ty.intInfo(target).bits;
2770 const int_ty = t.intTagType(mod);
2771 const bit_count = int_ty.intInfo(mod).bits;
28172772 assert(bit_count != 0);
28182773 return dg.context.intType(bit_count);
28192774 },
......@@ -2827,9 +2782,8 @@ pub const DeclGen = struct {
28272782 },
28282783 .Bool => return dg.context.intType(1),
28292784 .Pointer => {
2830 if (t.isSlice()) {
2831 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2832 const ptr_type = t.slicePtrFieldType(&buf);
2785 if (t.isSlice(mod)) {
2786 const ptr_type = t.slicePtrFieldType(mod);
28332787
28342788 const fields: [2]*llvm.Type = .{
28352789 try dg.lowerType(ptr_type),
......@@ -2837,49 +2791,41 @@ pub const DeclGen = struct {
28372791 };
28382792 return dg.context.structType(&fields, fields.len, .False);
28392793 }
2840 const ptr_info = t.ptrInfo().data;
2794 const ptr_info = t.ptrInfo(mod);
28412795 const llvm_addrspace = toLlvmAddressSpace(ptr_info.@"addrspace", target);
28422796 return dg.context.pointerType(llvm_addrspace);
28432797 },
2844 .Opaque => switch (t.tag()) {
2845 .@"opaque" => {
2846 const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
2847 if (gop.found_existing) return gop.value_ptr.*;
2798 .Opaque => {
2799 if (t.toIntern() == .anyopaque_type) return dg.context.intType(8);
28482800
2849 // The Type memory is ephemeral; since we want to store a longer-lived
2850 // reference, we need to copy it here.
2851 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
2801 const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
2802 if (gop.found_existing) return gop.value_ptr.*;
28522803
2853 const opaque_obj = t.castTag(.@"opaque").?.data;
2854 const name = try opaque_obj.getFullyQualifiedName(dg.module);
2855 defer gpa.free(name);
2804 const opaque_type = mod.intern_pool.indexToKey(t.toIntern()).opaque_type;
2805 const name = mod.intern_pool.stringToSlice(try mod.opaqueFullyQualifiedName(opaque_type));
28562806
2857 const llvm_struct_ty = dg.context.structCreateNamed(name);
2858 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2859 return llvm_struct_ty;
2860 },
2861 .anyopaque => return dg.context.intType(8),
2862 else => unreachable,
2807 const llvm_struct_ty = dg.context.structCreateNamed(name);
2808 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2809 return llvm_struct_ty;
28632810 },
28642811 .Array => {
2865 const elem_ty = t.childType();
2866 assert(elem_ty.onePossibleValue() == null);
2812 const elem_ty = t.childType(mod);
2813 if (std.debug.runtime_safety) assert((try elem_ty.onePossibleValue(mod)) == null);
28672814 const elem_llvm_ty = try dg.lowerType(elem_ty);
2868 const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null);
2815 const total_len = t.arrayLen(mod) + @boolToInt(t.sentinel(mod) != null);
28692816 return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));
28702817 },
28712818 .Vector => {
2872 const elem_type = try dg.lowerType(t.childType());
2873 return elem_type.vectorType(t.vectorLen());
2819 const elem_type = try dg.lowerType(t.childType(mod));
2820 return elem_type.vectorType(t.vectorLen(mod));
28742821 },
28752822 .Optional => {
2876 var buf: Type.Payload.ElemType = undefined;
2877 const child_ty = t.optionalChild(&buf);
2878 if (!child_ty.hasRuntimeBitsIgnoreComptime()) {
2823 const child_ty = t.optionalChild(mod);
2824 if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) {
28792825 return dg.context.intType(8);
28802826 }
28812827 const payload_llvm_ty = try dg.lowerType(child_ty);
2882 if (t.optionalReprIsPayload()) {
2828 if (t.optionalReprIsPayload(mod)) {
28832829 return payload_llvm_ty;
28842830 }
28852831
......@@ -2887,8 +2833,8 @@ pub const DeclGen = struct {
28872833 var fields_buf: [3]*llvm.Type = .{
28882834 payload_llvm_ty, dg.context.intType(8), undefined,
28892835 };
2890 const offset = child_ty.abiSize(target) + 1;
2891 const abi_size = t.abiSize(target);
2836 const offset = child_ty.abiSize(mod) + 1;
2837 const abi_size = t.abiSize(mod);
28922838 const padding = @intCast(c_uint, abi_size - offset);
28932839 if (padding == 0) {
28942840 return dg.context.structType(&fields_buf, 2, .False);
......@@ -2897,18 +2843,18 @@ pub const DeclGen = struct {
28972843 return dg.context.structType(&fields_buf, 3, .False);
28982844 },
28992845 .ErrorUnion => {
2900 const payload_ty = t.errorUnionPayload();
2901 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2846 const payload_ty = t.errorUnionPayload(mod);
2847 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
29022848 return try dg.lowerType(Type.anyerror);
29032849 }
29042850 const llvm_error_type = try dg.lowerType(Type.anyerror);
29052851 const llvm_payload_type = try dg.lowerType(payload_ty);
29062852
2907 const payload_align = payload_ty.abiAlignment(target);
2908 const error_align = Type.anyerror.abiAlignment(target);
2853 const payload_align = payload_ty.abiAlignment(mod);
2854 const error_align = Type.anyerror.abiAlignment(mod);
29092855
2910 const payload_size = payload_ty.abiSize(target);
2911 const error_size = Type.anyerror.abiSize(target);
2856 const payload_size = payload_ty.abiSize(mod);
2857 const error_size = Type.anyerror.abiSize(mod);
29122858
29132859 var fields_buf: [3]*llvm.Type = undefined;
29142860 if (error_align > payload_align) {
......@@ -2941,66 +2887,64 @@ pub const DeclGen = struct {
29412887 },
29422888 .ErrorSet => return dg.context.intType(16),
29432889 .Struct => {
2944 const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
2890 const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
29452891 if (gop.found_existing) return gop.value_ptr.*;
29462892
2947 // The Type memory is ephemeral; since we want to store a longer-lived
2948 // reference, we need to copy it here.
2949 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
2893 const struct_type = switch (mod.intern_pool.indexToKey(t.toIntern())) {
2894 .anon_struct_type => |tuple| {
2895 const llvm_struct_ty = dg.context.structCreateNamed("");
2896 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
29502897
2951 if (t.isSimpleTupleOrAnonStruct()) {
2952 const tuple = t.tupleFields();
2953 const llvm_struct_ty = dg.context.structCreateNamed("");
2954 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
2898 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
2899 defer llvm_field_types.deinit(gpa);
29552900
2956 var llvm_field_types: std.ArrayListUnmanaged(*llvm.Type) = .{};
2957 defer llvm_field_types.deinit(gpa);
2901 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
29582902
2959 try llvm_field_types.ensureUnusedCapacity(gpa, tuple.types.len);
2903 comptime assert(struct_layout_version == 2);
2904 var offset: u64 = 0;
2905 var big_align: u32 = 0;
29602906
2961 comptime assert(struct_layout_version == 2);
2962 var offset: u64 = 0;
2963 var big_align: u32 = 0;
2907 for (tuple.types, tuple.values) |field_ty, field_val| {
2908 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
29642909
2965 for (tuple.types, 0..) |field_ty, i| {
2966 const field_val = tuple.values[i];
2967 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
2910 const field_align = field_ty.toType().abiAlignment(mod);
2911 big_align = @max(big_align, field_align);
2912 const prev_offset = offset;
2913 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
29682914
2969 const field_align = field_ty.abiAlignment(target);
2970 big_align = @max(big_align, field_align);
2971 const prev_offset = offset;
2972 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
2915 const padding_len = offset - prev_offset;
2916 if (padding_len > 0) {
2917 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2918 try llvm_field_types.append(gpa, llvm_array_ty);
2919 }
2920 const field_llvm_ty = try dg.lowerType(field_ty.toType());
2921 try llvm_field_types.append(gpa, field_llvm_ty);
29732922
2974 const padding_len = offset - prev_offset;
2975 if (padding_len > 0) {
2976 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2977 try llvm_field_types.append(gpa, llvm_array_ty);
2923 offset += field_ty.toType().abiSize(mod);
29782924 }
2979 const field_llvm_ty = try dg.lowerType(field_ty);
2980 try llvm_field_types.append(gpa, field_llvm_ty);
2981
2982 offset += field_ty.abiSize(target);
2983 }
2984 {
2985 const prev_offset = offset;
2986 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2987 const padding_len = offset - prev_offset;
2988 if (padding_len > 0) {
2989 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2990 try llvm_field_types.append(gpa, llvm_array_ty);
2925 {
2926 const prev_offset = offset;
2927 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
2928 const padding_len = offset - prev_offset;
2929 if (padding_len > 0) {
2930 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
2931 try llvm_field_types.append(gpa, llvm_array_ty);
2932 }
29912933 }
2992 }
29932934
2994 llvm_struct_ty.structSetBody(
2995 llvm_field_types.items.ptr,
2996 @intCast(c_uint, llvm_field_types.items.len),
2997 .False,
2998 );
2935 llvm_struct_ty.structSetBody(
2936 llvm_field_types.items.ptr,
2937 @intCast(c_uint, llvm_field_types.items.len),
2938 .False,
2939 );
29992940
3000 return llvm_struct_ty;
3001 }
2941 return llvm_struct_ty;
2942 },
2943 .struct_type => |struct_type| struct_type,
2944 else => unreachable,
2945 };
30022946
3003 const struct_obj = t.castTag(.@"struct").?.data;
2947 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
30042948
30052949 if (struct_obj.layout == .Packed) {
30062950 assert(struct_obj.haveLayout());
......@@ -3009,8 +2953,7 @@ pub const DeclGen = struct {
30092953 return int_llvm_ty;
30102954 }
30112955
3012 const name = try struct_obj.getFullyQualifiedName(dg.module);
3013 defer gpa.free(name);
2956 const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(mod));
30142957
30152958 const llvm_struct_ty = dg.context.structCreateNamed(name);
30162959 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
......@@ -3027,11 +2970,11 @@ pub const DeclGen = struct {
30272970 var big_align: u32 = 1;
30282971 var any_underaligned_fields = false;
30292972
3030 var it = struct_obj.runtimeFieldIterator();
2973 var it = struct_obj.runtimeFieldIterator(mod);
30312974 while (it.next()) |field_and_index| {
30322975 const field = field_and_index.field;
3033 const field_align = field.alignment(target, struct_obj.layout);
3034 const field_ty_align = field.ty.abiAlignment(target);
2976 const field_align = field.alignment(mod, struct_obj.layout);
2977 const field_ty_align = field.ty.abiAlignment(mod);
30352978 any_underaligned_fields = any_underaligned_fields or
30362979 field_align < field_ty_align;
30372980 big_align = @max(big_align, field_align);
......@@ -3046,7 +2989,7 @@ pub const DeclGen = struct {
30462989 const field_llvm_ty = try dg.lowerType(field.ty);
30472990 try llvm_field_types.append(gpa, field_llvm_ty);
30482991
3049 offset += field.ty.abiSize(target);
2992 offset += field.ty.abiSize(mod);
30502993 }
30512994 {
30522995 const prev_offset = offset;
......@@ -3067,18 +3010,14 @@ pub const DeclGen = struct {
30673010 return llvm_struct_ty;
30683011 },
30693012 .Union => {
3070 const gop = try dg.object.type_map.getOrPutContext(gpa, t, .{ .mod = dg.module });
3013 const gop = try dg.object.type_map.getOrPut(gpa, t.toIntern());
30713014 if (gop.found_existing) return gop.value_ptr.*;
30723015
3073 // The Type memory is ephemeral; since we want to store a longer-lived
3074 // reference, we need to copy it here.
3075 gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
3076
3077 const layout = t.unionGetLayout(target);
3078 const union_obj = t.cast(Type.Payload.Union).?.data;
3016 const layout = t.unionGetLayout(mod);
3017 const union_obj = mod.typeToUnion(t).?;
30793018
30803019 if (union_obj.layout == .Packed) {
3081 const bitsize = @intCast(c_uint, t.bitSize(target));
3020 const bitsize = @intCast(c_uint, t.bitSize(mod));
30823021 const int_llvm_ty = dg.context.intType(bitsize);
30833022 gop.value_ptr.* = int_llvm_ty;
30843023 return int_llvm_ty;
......@@ -3090,8 +3029,7 @@ pub const DeclGen = struct {
30903029 return enum_tag_llvm_ty;
30913030 }
30923031
3093 const name = try union_obj.getFullyQualifiedName(dg.module);
3094 defer gpa.free(name);
3032 const name = mod.intern_pool.stringToSlice(try union_obj.getFullyQualifiedName(mod));
30953033
30963034 const llvm_union_ty = dg.context.structCreateNamed(name);
30973035 gop.value_ptr.* = llvm_union_ty; // must be done before any recursive calls
......@@ -3155,25 +3093,21 @@ pub const DeclGen = struct {
31553093 }
31563094
31573095 fn lowerTypeFn(dg: *DeclGen, fn_ty: Type) Allocator.Error!*llvm.Type {
3158 const target = dg.module.getTarget();
3159 const fn_info = fn_ty.fnInfo();
3096 const mod = dg.module;
3097 const fn_info = mod.typeToFunc(fn_ty).?;
31603098 const llvm_ret_ty = try lowerFnRetTy(dg, fn_info);
31613099
31623100 var llvm_params = std.ArrayList(*llvm.Type).init(dg.gpa);
31633101 defer llvm_params.deinit();
31643102
3165 if (firstParamSRet(fn_info, target)) {
3103 if (firstParamSRet(fn_info, mod)) {
31663104 try llvm_params.append(dg.context.pointerType(0));
31673105 }
31683106
3169 if (fn_info.return_type.isError() and
3170 dg.module.comp.bin_file.options.error_return_tracing)
3107 if (fn_info.return_type.toType().isError(mod) and
3108 mod.comp.bin_file.options.error_return_tracing)
31713109 {
3172 var ptr_ty_payload: Type.Payload.ElemType = .{
3173 .base = .{ .tag = .single_mut_pointer },
3174 .data = dg.object.getStackTraceType(),
3175 };
3176 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
3110 const ptr_ty = try mod.singleMutPtrType(try dg.object.getStackTraceType());
31773111 try llvm_params.append(try dg.lowerType(ptr_ty));
31783112 }
31793113
......@@ -3181,25 +3115,23 @@ pub const DeclGen = struct {
31813115 while (it.next()) |lowering| switch (lowering) {
31823116 .no_bits => continue,
31833117 .byval => {
3184 const param_ty = fn_info.param_types[it.zig_index - 1];
3118 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
31853119 try llvm_params.append(try dg.lowerType(param_ty));
31863120 },
31873121 .byref, .byref_mut => {
31883122 try llvm_params.append(dg.context.pointerType(0));
31893123 },
31903124 .abi_sized_int => {
3191 const param_ty = fn_info.param_types[it.zig_index - 1];
3192 const abi_size = @intCast(c_uint, param_ty.abiSize(target));
3125 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3126 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));
31933127 try llvm_params.append(dg.context.intType(abi_size * 8));
31943128 },
31953129 .slice => {
3196 const param_ty = fn_info.param_types[it.zig_index - 1];
3197 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3198 var opt_buf: Type.Payload.ElemType = undefined;
3199 const ptr_ty = if (param_ty.zigTypeTag() == .Optional)
3200 param_ty.optionalChild(&opt_buf).slicePtrFieldType(&buf)
3130 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3131 const ptr_ty = if (param_ty.zigTypeTag(mod) == .Optional)
3132 param_ty.optionalChild(mod).slicePtrFieldType(mod)
32013133 else
3202 param_ty.slicePtrFieldType(&buf);
3134 param_ty.slicePtrFieldType(mod);
32033135 const ptr_llvm_ty = try dg.lowerType(ptr_ty);
32043136 const len_llvm_ty = try dg.lowerType(Type.usize);
32053137
......@@ -3214,8 +3146,8 @@ pub const DeclGen = struct {
32143146 try llvm_params.append(dg.context.intType(16));
32153147 },
32163148 .float_array => |count| {
3217 const param_ty = fn_info.param_types[it.zig_index - 1];
3218 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty).?);
3149 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
3150 const float_ty = try dg.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, mod).?);
32193151 const field_count = @intCast(c_uint, count);
32203152 const arr_ty = float_ty.arrayType(field_count);
32213153 try llvm_params.append(arr_ty);
......@@ -3239,11 +3171,12 @@ pub const DeclGen = struct {
32393171 /// being a zero bit type, but it should still be lowered as an i8 in such case.
32403172 /// There are other similar cases handled here as well.
32413173 fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*llvm.Type {
3242 const lower_elem_ty = switch (elem_ty.zigTypeTag()) {
3174 const mod = dg.module;
3175 const lower_elem_ty = switch (elem_ty.zigTypeTag(mod)) {
32433176 .Opaque => true,
3244 .Fn => !elem_ty.fnInfo().is_generic,
3245 .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(),
3246 else => elem_ty.hasRuntimeBitsIgnoreComptime(),
3177 .Fn => !mod.typeToFunc(elem_ty).?.is_generic,
3178 .Array => elem_ty.childType(mod).hasRuntimeBitsIgnoreComptime(mod),
3179 else => elem_ty.hasRuntimeBitsIgnoreComptime(mod),
32473180 };
32483181 const llvm_elem_ty = if (lower_elem_ty)
32493182 try dg.lowerType(elem_ty)
......@@ -3254,59 +3187,132 @@ pub const DeclGen = struct {
32543187 }
32553188
32563189 fn lowerValue(dg: *DeclGen, arg_tv: TypedValue) Error!*llvm.Value {
3190 const mod = dg.module;
3191 const target = mod.getTarget();
32573192 var tv = arg_tv;
3258 if (tv.val.castTag(.runtime_value)) |rt| {
3259 tv.val = rt.data;
3193 switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
3194 .runtime_value => |rt| tv.val = rt.val.toValue(),
3195 else => {},
32603196 }
3261 if (tv.val.isUndef()) {
3197 if (tv.val.isUndefDeep(mod)) {
32623198 const llvm_type = try dg.lowerType(tv.ty);
32633199 return llvm_type.getUndef();
32643200 }
3265 const target = dg.module.getTarget();
32663201
3267 switch (tv.ty.zigTypeTag()) {
3268 .Bool => {
3269 const llvm_type = try dg.lowerType(tv.ty);
3270 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
3271 },
3272 // TODO this duplicates code with Pointer but they should share the handling
3273 // of the tv.val.tag() and then Int should do extra constPtrToInt on top
3274 .Int => switch (tv.val.tag()) {
3275 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
3276 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
3277 else => {
3278 var bigint_space: Value.BigIntSpace = undefined;
3279 const bigint = tv.val.toBigInt(&bigint_space, target);
3280 const int_info = tv.ty.intInfo(target);
3281 assert(int_info.bits != 0);
3282 const llvm_type = dg.context.intType(int_info.bits);
3283
3284 const unsigned_val = v: {
3285 if (bigint.limbs.len == 1) {
3286 break :v llvm_type.constInt(bigint.limbs[0], .False);
3287 }
3288 if (@sizeOf(usize) == @sizeOf(u64)) {
3289 break :v llvm_type.constIntOfArbitraryPrecision(
3290 @intCast(c_uint, bigint.limbs.len),
3291 bigint.limbs.ptr,
3292 );
3293 }
3294 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
3295 };
3296 if (!bigint.positive) {
3297 return llvm.constNeg(unsigned_val);
3298 }
3299 return unsigned_val;
3202 const val_key = mod.intern_pool.indexToKey(tv.val.toIntern());
3203 switch (val_key) {
3204 .int_type,
3205 .ptr_type,
3206 .array_type,
3207 .vector_type,
3208 .opt_type,
3209 .anyframe_type,
3210 .error_union_type,
3211 .simple_type,
3212 .struct_type,
3213 .anon_struct_type,
3214 .union_type,
3215 .opaque_type,
3216 .enum_type,
3217 .func_type,
3218 .error_set_type,
3219 .inferred_error_set_type,
3220 => unreachable, // types, not values
3221
3222 .undef, .runtime_value => unreachable, // handled above
3223 .simple_value => |simple_value| switch (simple_value) {
3224 .undefined,
3225 .void,
3226 .null,
3227 .empty_struct,
3228 .@"unreachable",
3229 .generic_poison,
3230 => unreachable, // non-runtime values
3231 .false, .true => {
3232 const llvm_type = try dg.lowerType(tv.ty);
3233 return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull();
33003234 },
33013235 },
3302 .Enum => {
3303 var int_buffer: Value.Payload.U64 = undefined;
3304 const int_val = tv.enumToInt(&int_buffer);
3236 .variable,
3237 .enum_literal,
3238 .empty_enum_value,
3239 => unreachable, // non-runtime values
3240 .extern_func, .func => {
3241 const fn_decl_index = switch (val_key) {
3242 .extern_func => |extern_func| extern_func.decl,
3243 .func => |func| mod.funcPtr(func.index).owner_decl,
3244 else => unreachable,
3245 };
3246 const fn_decl = dg.module.declPtr(fn_decl_index);
3247 try dg.module.markDeclAlive(fn_decl);
3248 return dg.resolveLlvmFunction(fn_decl_index);
3249 },
3250 .int => {
3251 var bigint_space: Value.BigIntSpace = undefined;
3252 const bigint = tv.val.toBigInt(&bigint_space, mod);
3253 return lowerBigInt(dg, tv.ty, bigint);
3254 },
3255 .err => |err| {
3256 const llvm_ty = try dg.lowerType(Type.anyerror);
3257 const int = try mod.getErrorValue(err.name);
3258 return llvm_ty.constInt(int, .False);
3259 },
3260 .error_union => |error_union| {
3261 const err_tv: TypedValue = switch (error_union.val) {
3262 .err_name => |err_name| .{
3263 .ty = tv.ty.errorUnionSet(mod),
3264 .val = (try mod.intern(.{ .err = .{
3265 .ty = tv.ty.errorUnionSet(mod).toIntern(),
3266 .name = err_name,
3267 } })).toValue(),
3268 },
3269 .payload => .{
3270 .ty = Type.err_int,
3271 .val = try mod.intValue(Type.err_int, 0),
3272 },
3273 };
3274 const payload_type = tv.ty.errorUnionPayload(mod);
3275 if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
3276 // We use the error type directly as the type.
3277 return dg.lowerValue(err_tv);
3278 }
3279
3280 const payload_align = payload_type.abiAlignment(mod);
3281 const error_align = err_tv.ty.abiAlignment(mod);
3282 const llvm_error_value = try dg.lowerValue(err_tv);
3283 const llvm_payload_value = try dg.lowerValue(.{
3284 .ty = payload_type,
3285 .val = switch (error_union.val) {
3286 .err_name => try mod.intern(.{ .undef = payload_type.toIntern() }),
3287 .payload => |payload| payload,
3288 }.toValue(),
3289 });
3290 var fields_buf: [3]*llvm.Value = undefined;
3291
3292 const llvm_ty = try dg.lowerType(tv.ty);
3293 const llvm_field_count = llvm_ty.countStructElementTypes();
3294 if (llvm_field_count > 2) {
3295 assert(llvm_field_count == 3);
3296 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();
3297 }
3298
3299 if (error_align > payload_align) {
3300 fields_buf[0] = llvm_error_value;
3301 fields_buf[1] = llvm_payload_value;
3302 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3303 } else {
3304 fields_buf[0] = llvm_payload_value;
3305 fields_buf[1] = llvm_error_value;
3306 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3307 }
3308 },
3309 .enum_tag => {
3310 const int_val = try tv.enumToInt(mod);
33053311
33063312 var bigint_space: Value.BigIntSpace = undefined;
3307 const bigint = int_val.toBigInt(&bigint_space, target);
3313 const bigint = int_val.toBigInt(&bigint_space, mod);
33083314
3309 const int_info = tv.ty.intInfo(target);
3315 const int_info = tv.ty.intInfo(mod);
33103316 const llvm_type = dg.context.intType(int_info.bits);
33113317
33123318 const unsigned_val = v: {
......@@ -3326,29 +3332,29 @@ pub const DeclGen = struct {
33263332 }
33273333 return unsigned_val;
33283334 },
3329 .Float => {
3335 .float => {
33303336 const llvm_ty = try dg.lowerType(tv.ty);
33313337 switch (tv.ty.floatBits(target)) {
33323338 16 => {
3333 const repr = @bitCast(u16, tv.val.toFloat(f16));
3339 const repr = @bitCast(u16, tv.val.toFloat(f16, mod));
33343340 const llvm_i16 = dg.context.intType(16);
33353341 const int = llvm_i16.constInt(repr, .False);
33363342 return int.constBitCast(llvm_ty);
33373343 },
33383344 32 => {
3339 const repr = @bitCast(u32, tv.val.toFloat(f32));
3345 const repr = @bitCast(u32, tv.val.toFloat(f32, mod));
33403346 const llvm_i32 = dg.context.intType(32);
33413347 const int = llvm_i32.constInt(repr, .False);
33423348 return int.constBitCast(llvm_ty);
33433349 },
33443350 64 => {
3345 const repr = @bitCast(u64, tv.val.toFloat(f64));
3351 const repr = @bitCast(u64, tv.val.toFloat(f64, mod));
33463352 const llvm_i64 = dg.context.intType(64);
33473353 const int = llvm_i64.constInt(repr, .False);
33483354 return int.constBitCast(llvm_ty);
33493355 },
33503356 80 => {
3351 const float = tv.val.toFloat(f80);
3357 const float = tv.val.toFloat(f80, mod);
33523358 const repr = std.math.break_f80(float);
33533359 const llvm_i80 = dg.context.intType(80);
33543360 var x = llvm_i80.constInt(repr.exp, .False);
......@@ -3361,7 +3367,7 @@ pub const DeclGen = struct {
33613367 }
33623368 },
33633369 128 => {
3364 var buf: [2]u64 = @bitCast([2]u64, tv.val.toFloat(f128));
3370 var buf: [2]u64 = @bitCast([2]u64, tv.val.toFloat(f128, mod));
33653371 // LLVM seems to require that the lower half of the f128 be placed first
33663372 // in the buffer.
33673373 if (native_endian == .Big) {
......@@ -3373,204 +3379,60 @@ pub const DeclGen = struct {
33733379 else => unreachable,
33743380 }
33753381 },
3376 .Pointer => switch (tv.val.tag()) {
3377 .decl_ref_mut => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref_mut).?.data.decl_index),
3378 .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data),
3379 .variable => {
3380 const decl_index = tv.val.castTag(.variable).?.data.owner_decl;
3381 const decl = dg.module.declPtr(decl_index);
3382 dg.module.markDeclAlive(decl);
3383
3384 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
3385 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
3386
3387 const val = try dg.resolveGlobalDecl(decl_index);
3388 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
3389 val.constAddrSpaceCast(dg.context.pointerType(llvm_wanted_addrspace))
3390 else
3391 val;
3392 return addrspace_casted_ptr;
3393 },
3394 .slice => {
3395 const slice = tv.val.castTag(.slice).?.data;
3396 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
3397 const fields: [2]*llvm.Value = .{
3398 try dg.lowerValue(.{
3399 .ty = tv.ty.slicePtrFieldType(&buf),
3400 .val = slice.ptr,
3401 }),
3402 try dg.lowerValue(.{
3403 .ty = Type.usize,
3404 .val = slice.len,
3405 }),
3406 };
3407 return dg.context.constStruct(&fields, fields.len, .False);
3408 },
3409 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
3410 const llvm_usize = try dg.lowerType(Type.usize);
3411 const llvm_int = llvm_usize.constInt(tv.val.toUnsignedInt(target), .False);
3412 return llvm_int.constIntToPtr(try dg.lowerType(tv.ty));
3413 },
3414 .field_ptr, .opt_payload_ptr, .eu_payload_ptr, .elem_ptr => {
3415 return dg.lowerParentPtr(tv.val, tv.ty.ptrInfo().data.bit_offset % 8 == 0);
3416 },
3417 .null_value, .zero => {
3418 const llvm_type = try dg.lowerType(tv.ty);
3419 return llvm_type.constNull();
3420 },
3421 .opt_payload => {
3422 const payload = tv.val.castTag(.opt_payload).?.data;
3423 return dg.lowerParentPtr(payload, tv.ty.ptrInfo().data.bit_offset % 8 == 0);
3424 },
3425 else => |tag| return dg.todo("implement const of pointer type '{}' ({})", .{
3426 tv.ty.fmtDebug(), tag,
3427 }),
3428 },
3429 .Array => switch (tv.val.tag()) {
3430 .bytes => {
3431 const bytes = tv.val.castTag(.bytes).?.data;
3432 return dg.context.constString(
3433 bytes.ptr,
3434 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel()),
3435 .True, // Don't null terminate. Bytes has the sentinel, if any.
3436 );
3437 },
3438 .str_lit => {
3439 const str_lit = tv.val.castTag(.str_lit).?.data;
3440 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
3441 if (tv.ty.sentinel()) |sent_val| {
3442 const byte = @intCast(u8, sent_val.toUnsignedInt(target));
3443 if (byte == 0 and bytes.len > 0) {
3444 return dg.context.constString(
3445 bytes.ptr,
3446 @intCast(c_uint, bytes.len),
3447 .False, // Yes, null terminate.
3448 );
3449 }
3450 var array = std.ArrayList(u8).init(dg.gpa);
3451 defer array.deinit();
3452 try array.ensureUnusedCapacity(bytes.len + 1);
3453 array.appendSliceAssumeCapacity(bytes);
3454 array.appendAssumeCapacity(byte);
3455 return dg.context.constString(
3456 array.items.ptr,
3457 @intCast(c_uint, array.items.len),
3458 .True, // Don't null terminate.
3459 );
3460 } else {
3461 return dg.context.constString(
3462 bytes.ptr,
3463 @intCast(c_uint, bytes.len),
3464 .True, // Don't null terminate. `bytes` has the sentinel, if any.
3465 );
3466 }
3467 },
3468 .aggregate => {
3469 const elem_vals = tv.val.castTag(.aggregate).?.data;
3470 const elem_ty = tv.ty.elemType();
3471 const gpa = dg.gpa;
3472 const len = @intCast(usize, tv.ty.arrayLenIncludingSentinel());
3473 const llvm_elems = try gpa.alloc(*llvm.Value, len);
3474 defer gpa.free(llvm_elems);
3475 var need_unnamed = false;
3476 for (elem_vals[0..len], 0..) |elem_val, i| {
3477 llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val });
3478 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
3479 }
3480 if (need_unnamed) {
3481 return dg.context.constStruct(
3482 llvm_elems.ptr,
3483 @intCast(c_uint, llvm_elems.len),
3484 .True,
3485 );
3486 } else {
3487 const llvm_elem_ty = try dg.lowerType(elem_ty);
3488 return llvm_elem_ty.constArray(
3489 llvm_elems.ptr,
3490 @intCast(c_uint, llvm_elems.len),
3491 );
3492 }
3493 },
3494 .repeated => {
3495 const val = tv.val.castTag(.repeated).?.data;
3496 const elem_ty = tv.ty.elemType();
3497 const sentinel = tv.ty.sentinel();
3498 const len = @intCast(usize, tv.ty.arrayLen());
3499 const len_including_sent = len + @boolToInt(sentinel != null);
3500 const gpa = dg.gpa;
3501 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);
3502 defer gpa.free(llvm_elems);
3503
3504 var need_unnamed = false;
3505 if (len != 0) {
3506 for (llvm_elems[0..len]) |*elem| {
3507 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val });
3508 }
3509 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3510 }
3511
3512 if (sentinel) |sent| {
3513 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3514 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3515 }
3516
3517 if (need_unnamed) {
3518 return dg.context.constStruct(
3519 llvm_elems.ptr,
3520 @intCast(c_uint, llvm_elems.len),
3521 .True,
3522 );
3523 } else {
3524 const llvm_elem_ty = try dg.lowerType(elem_ty);
3525 return llvm_elem_ty.constArray(
3526 llvm_elems.ptr,
3527 @intCast(c_uint, llvm_elems.len),
3528 );
3529 }
3530 },
3531 .empty_array_sentinel => {
3532 const elem_ty = tv.ty.elemType();
3533 const sent_val = tv.ty.sentinel().?;
3534 const sentinel = try dg.lowerValue(.{ .ty = elem_ty, .val = sent_val });
3535 const llvm_elems: [1]*llvm.Value = .{sentinel};
3536 const need_unnamed = dg.isUnnamedType(elem_ty, llvm_elems[0]);
3537 if (need_unnamed) {
3538 return dg.context.constStruct(&llvm_elems, llvm_elems.len, .True);
3539 } else {
3540 const llvm_elem_ty = try dg.lowerType(elem_ty);
3541 return llvm_elem_ty.constArray(&llvm_elems, llvm_elems.len);
3542 }
3543 },
3544 else => unreachable,
3382 .ptr => |ptr| {
3383 const ptr_tv: TypedValue = switch (ptr.len) {
3384 .none => tv,
3385 else => .{ .ty = tv.ty.slicePtrFieldType(mod), .val = tv.val.slicePtr(mod) },
3386 };
3387 const llvm_ptr_val = switch (ptr.addr) {
3388 .decl => |decl| try dg.lowerDeclRefValue(ptr_tv, decl),
3389 .mut_decl => |mut_decl| try dg.lowerDeclRefValue(ptr_tv, mut_decl.decl),
3390 .int => |int| try dg.lowerIntAsPtr(int.toValue()),
3391 .eu_payload,
3392 .opt_payload,
3393 .elem,
3394 .field,
3395 => try dg.lowerParentPtr(ptr_tv.val, ptr_tv.ty.ptrInfo(mod).bit_offset % 8 == 0),
3396 .comptime_field => unreachable,
3397 };
3398 switch (ptr.len) {
3399 .none => return llvm_ptr_val,
3400 else => {
3401 const fields: [2]*llvm.Value = .{
3402 llvm_ptr_val,
3403 try dg.lowerValue(.{ .ty = Type.usize, .val = ptr.len.toValue() }),
3404 };
3405 return dg.context.constStruct(&fields, fields.len, .False);
3406 },
3407 }
35453408 },
3546 .Optional => {
3409 .opt => |opt| {
35473410 comptime assert(optional_layout_version == 3);
3548 var buf: Type.Payload.ElemType = undefined;
3549 const payload_ty = tv.ty.optionalChild(&buf);
3411 const payload_ty = tv.ty.optionalChild(mod);
35503412
35513413 const llvm_i8 = dg.context.intType(8);
3552 const is_pl = !tv.val.isNull();
3553 const non_null_bit = if (is_pl) llvm_i8.constInt(1, .False) else llvm_i8.constNull();
3554 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3414 const non_null_bit = switch (opt.val) {
3415 .none => llvm_i8.constNull(),
3416 else => llvm_i8.constInt(1, .False),
3417 };
3418 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
35553419 return non_null_bit;
35563420 }
35573421 const llvm_ty = try dg.lowerType(tv.ty);
3558 if (tv.ty.optionalReprIsPayload()) {
3559 if (tv.val.castTag(.opt_payload)) |payload| {
3560 return dg.lowerValue(.{ .ty = payload_ty, .val = payload.data });
3561 } else if (is_pl) {
3562 return dg.lowerValue(.{ .ty = payload_ty, .val = tv.val });
3563 } else {
3564 return llvm_ty.constNull();
3565 }
3566 }
3567 assert(payload_ty.zigTypeTag() != .Fn);
3422 if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
3423 .none => llvm_ty.constNull(),
3424 else => |payload| dg.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }),
3425 };
3426 assert(payload_ty.zigTypeTag(mod) != .Fn);
35683427
35693428 const llvm_field_count = llvm_ty.countStructElementTypes();
35703429 var fields_buf: [3]*llvm.Value = undefined;
35713430 fields_buf[0] = try dg.lowerValue(.{
35723431 .ty = payload_ty,
3573 .val = if (tv.val.castTag(.opt_payload)) |pl| pl.data else Value.initTag(.undef),
3432 .val = switch (opt.val) {
3433 .none => try mod.intern(.{ .undef = payload_ty.toIntern() }),
3434 else => |payload| payload,
3435 }.toValue(),
35743436 });
35753437 fields_buf[1] = non_null_bit;
35763438 if (llvm_field_count > 2) {
......@@ -3579,76 +3441,100 @@ pub const DeclGen = struct {
35793441 }
35803442 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
35813443 },
3582 .Fn => {
3583 const fn_decl_index = switch (tv.val.tag()) {
3584 .extern_fn => tv.val.castTag(.extern_fn).?.data.owner_decl,
3585 .function => tv.val.castTag(.function).?.data.owner_decl,
3586 else => unreachable,
3587 };
3588 const fn_decl = dg.module.declPtr(fn_decl_index);
3589 dg.module.markDeclAlive(fn_decl);
3590 return dg.resolveLlvmFunction(fn_decl_index);
3591 },
3592 .ErrorSet => {
3593 const llvm_ty = try dg.lowerType(Type.anyerror);
3594 switch (tv.val.tag()) {
3595 .@"error" => {
3596 const err_name = tv.val.castTag(.@"error").?.data.name;
3597 const kv = try dg.module.getErrorValue(err_name);
3598 return llvm_ty.constInt(kv.value, .False);
3599 },
3600 else => {
3601 // In this case we are rendering an error union which has a 0 bits payload.
3602 return llvm_ty.constNull();
3444 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(tv.ty.toIntern())) {
3445 .array_type => switch (aggregate.storage) {
3446 .bytes => |bytes| return dg.context.constString(
3447 bytes.ptr,
3448 @intCast(c_uint, tv.ty.arrayLenIncludingSentinel(mod)),
3449 .True, // Don't null terminate. Bytes has the sentinel, if any.
3450 ),
3451 .elems => |elem_vals| {
3452 const elem_ty = tv.ty.childType(mod);
3453 const gpa = dg.gpa;
3454 const llvm_elems = try gpa.alloc(*llvm.Value, elem_vals.len);
3455 defer gpa.free(llvm_elems);
3456 var need_unnamed = false;
3457 for (elem_vals, 0..) |elem_val, i| {
3458 llvm_elems[i] = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_val.toValue() });
3459 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[i]);
3460 }
3461 if (need_unnamed) {
3462 return dg.context.constStruct(
3463 llvm_elems.ptr,
3464 @intCast(c_uint, llvm_elems.len),
3465 .True,
3466 );
3467 } else {
3468 const llvm_elem_ty = try dg.lowerType(elem_ty);
3469 return llvm_elem_ty.constArray(
3470 llvm_elems.ptr,
3471 @intCast(c_uint, llvm_elems.len),
3472 );
3473 }
36033474 },
3604 }
3605 },
3606 .ErrorUnion => {
3607 const payload_type = tv.ty.errorUnionPayload();
3608 const is_pl = tv.val.errorUnionIsPayload();
3609
3610 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
3611 // We use the error type directly as the type.
3612 const err_val = if (!is_pl) tv.val else Value.initTag(.zero);
3613 return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val });
3614 }
3615
3616 const payload_align = payload_type.abiAlignment(target);
3617 const error_align = Type.anyerror.abiAlignment(target);
3618 const llvm_error_value = try dg.lowerValue(.{
3619 .ty = Type.anyerror,
3620 .val = if (is_pl) Value.initTag(.zero) else tv.val,
3621 });
3622 const llvm_payload_value = try dg.lowerValue(.{
3623 .ty = payload_type,
3624 .val = if (tv.val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef),
3625 });
3626 var fields_buf: [3]*llvm.Value = undefined;
3475 .repeated_elem => |val| {
3476 const elem_ty = tv.ty.childType(mod);
3477 const sentinel = tv.ty.sentinel(mod);
3478 const len = @intCast(usize, tv.ty.arrayLen(mod));
3479 const len_including_sent = len + @boolToInt(sentinel != null);
3480 const gpa = dg.gpa;
3481 const llvm_elems = try gpa.alloc(*llvm.Value, len_including_sent);
3482 defer gpa.free(llvm_elems);
3483
3484 var need_unnamed = false;
3485 if (len != 0) {
3486 for (llvm_elems[0..len]) |*elem| {
3487 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val.toValue() });
3488 }
3489 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[0]);
3490 }
36273491
3628 const llvm_ty = try dg.lowerType(tv.ty);
3629 const llvm_field_count = llvm_ty.countStructElementTypes();
3630 if (llvm_field_count > 2) {
3631 assert(llvm_field_count == 3);
3632 fields_buf[2] = llvm_ty.structGetTypeAtIndex(2).getUndef();
3633 }
3492 if (sentinel) |sent| {
3493 llvm_elems[len] = try dg.lowerValue(.{ .ty = elem_ty, .val = sent });
3494 need_unnamed = need_unnamed or dg.isUnnamedType(elem_ty, llvm_elems[len]);
3495 }
36343496
3635 if (error_align > payload_align) {
3636 fields_buf[0] = llvm_error_value;
3637 fields_buf[1] = llvm_payload_value;
3638 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3639 } else {
3640 fields_buf[0] = llvm_payload_value;
3641 fields_buf[1] = llvm_error_value;
3642 return dg.context.constStruct(&fields_buf, llvm_field_count, .False);
3643 }
3644 },
3645 .Struct => {
3646 const llvm_struct_ty = try dg.lowerType(tv.ty);
3647 const field_vals = tv.val.castTag(.aggregate).?.data;
3648 const gpa = dg.gpa;
3497 if (need_unnamed) {
3498 return dg.context.constStruct(
3499 llvm_elems.ptr,
3500 @intCast(c_uint, llvm_elems.len),
3501 .True,
3502 );
3503 } else {
3504 const llvm_elem_ty = try dg.lowerType(elem_ty);
3505 return llvm_elem_ty.constArray(
3506 llvm_elems.ptr,
3507 @intCast(c_uint, llvm_elems.len),
3508 );
3509 }
3510 },
3511 },
3512 .vector_type => |vector_type| {
3513 const elem_ty = vector_type.child.toType();
3514 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_type.len);
3515 defer dg.gpa.free(llvm_elems);
3516 const llvm_i8 = dg.context.intType(8);
3517 for (llvm_elems, 0..) |*llvm_elem, i| {
3518 llvm_elem.* = switch (aggregate.storage) {
3519 .bytes => |bytes| llvm_i8.constInt(bytes[i], .False),
3520 .elems => |elems| try dg.lowerValue(.{
3521 .ty = elem_ty,
3522 .val = elems[i].toValue(),
3523 }),
3524 .repeated_elem => |elem| try dg.lowerValue(.{
3525 .ty = elem_ty,
3526 .val = elem.toValue(),
3527 }),
3528 };
3529 }
3530 return llvm.constVector(
3531 llvm_elems.ptr,
3532 @intCast(c_uint, llvm_elems.len),
3533 );
3534 },
3535 .anon_struct_type => |tuple| {
3536 const gpa = dg.gpa;
36493537
3650 if (tv.ty.isSimpleTupleOrAnonStruct()) {
3651 const tuple = tv.ty.tupleFields();
36523538 var llvm_fields: std.ArrayListUnmanaged(*llvm.Value) = .{};
36533539 defer llvm_fields.deinit(gpa);
36543540
......@@ -3659,11 +3545,11 @@ pub const DeclGen = struct {
36593545 var big_align: u32 = 0;
36603546 var need_unnamed = false;
36613547
3662 for (tuple.types, 0..) |field_ty, i| {
3663 if (tuple.values[i].tag() != .unreachable_value) continue;
3664 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
3548 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3549 if (field_val != .none) continue;
3550 if (!field_ty.toType().hasRuntimeBitsIgnoreComptime(mod)) continue;
36653551
3666 const field_align = field_ty.abiAlignment(target);
3552 const field_align = field_ty.toType().abiAlignment(mod);
36673553 big_align = @max(big_align, field_align);
36683554 const prev_offset = offset;
36693555 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
......@@ -3677,15 +3563,15 @@ pub const DeclGen = struct {
36773563 }
36783564
36793565 const field_llvm_val = try dg.lowerValue(.{
3680 .ty = field_ty,
3681 .val = field_vals[i],
3566 .ty = field_ty.toType(),
3567 .val = try tv.val.fieldValue(mod, i),
36823568 });
36833569
3684 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field_llvm_val);
3570 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty.toType(), field_llvm_val);
36853571
36863572 llvm_fields.appendAssumeCapacity(field_llvm_val);
36873573
3688 offset += field_ty.abiSize(target);
3574 offset += field_ty.toType().abiSize(mod);
36893575 }
36903576 {
36913577 const prev_offset = offset;
......@@ -3704,132 +3590,142 @@ pub const DeclGen = struct {
37043590 .False,
37053591 );
37063592 } else {
3593 const llvm_struct_ty = try dg.lowerType(tv.ty);
37073594 return llvm_struct_ty.constNamedStruct(
37083595 llvm_fields.items.ptr,
37093596 @intCast(c_uint, llvm_fields.items.len),
37103597 );
37113598 }
3712 }
3713
3714 const struct_obj = tv.ty.castTag(.@"struct").?.data;
3715
3716 if (struct_obj.layout == .Packed) {
3717 assert(struct_obj.haveLayout());
3718 const big_bits = struct_obj.backing_int_ty.bitSize(target);
3719 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3720 const fields = struct_obj.fields.values();
3721 comptime assert(Type.packed_struct_layout_version == 2);
3722 var running_int: *llvm.Value = int_llvm_ty.constNull();
3723 var running_bits: u16 = 0;
3724 for (field_vals, 0..) |field_val, i| {
3725 const field = fields[i];
3726 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
3599 },
3600 .struct_type => |struct_type| {
3601 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3602 const llvm_struct_ty = try dg.lowerType(tv.ty);
3603 const gpa = dg.gpa;
37273604
3728 const non_int_val = try dg.lowerValue(.{
3729 .ty = field.ty,
3730 .val = field_val,
3731 });
3732 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
3733 const small_int_ty = dg.context.intType(ty_bit_size);
3734 const small_int_val = if (field.ty.isPtrAtRuntime())
3735 non_int_val.constPtrToInt(small_int_ty)
3736 else
3737 non_int_val.constBitCast(small_int_ty);
3738 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3739 // If the field is as large as the entire packed struct, this
3740 // zext would go from, e.g. i16 to i16. This is legal with
3741 // constZExtOrBitCast but not legal with constZExt.
3742 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
3743 const shifted = extended_int_val.constShl(shift_rhs);
3744 running_int = running_int.constOr(shifted);
3745 running_bits += ty_bit_size;
3605 if (struct_obj.layout == .Packed) {
3606 assert(struct_obj.haveLayout());
3607 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
3608 const int_llvm_ty = dg.context.intType(@intCast(c_uint, big_bits));
3609 const fields = struct_obj.fields.values();
3610 comptime assert(Type.packed_struct_layout_version == 2);
3611 var running_int: *llvm.Value = int_llvm_ty.constNull();
3612 var running_bits: u16 = 0;
3613 for (fields, 0..) |field, i| {
3614 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
3615
3616 const non_int_val = try dg.lowerValue(.{
3617 .ty = field.ty,
3618 .val = try tv.val.fieldValue(mod, i),
3619 });
3620 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
3621 const small_int_ty = dg.context.intType(ty_bit_size);
3622 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
3623 non_int_val.constPtrToInt(small_int_ty)
3624 else
3625 non_int_val.constBitCast(small_int_ty);
3626 const shift_rhs = int_llvm_ty.constInt(running_bits, .False);
3627 // If the field is as large as the entire packed struct, this
3628 // zext would go from, e.g. i16 to i16. This is legal with
3629 // constZExtOrBitCast but not legal with constZExt.
3630 const extended_int_val = small_int_val.constZExtOrBitCast(int_llvm_ty);
3631 const shifted = extended_int_val.constShl(shift_rhs);
3632 running_int = running_int.constOr(shifted);
3633 running_bits += ty_bit_size;
3634 }
3635 return running_int;
37463636 }
3747 return running_int;
3748 }
37493637
3750 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3751 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3752 defer llvm_fields.deinit(gpa);
3638 const llvm_field_count = llvm_struct_ty.countStructElementTypes();
3639 var llvm_fields = try std.ArrayListUnmanaged(*llvm.Value).initCapacity(gpa, llvm_field_count);
3640 defer llvm_fields.deinit(gpa);
37533641
3754 comptime assert(struct_layout_version == 2);
3755 var offset: u64 = 0;
3756 var big_align: u32 = 0;
3757 var need_unnamed = false;
3642 comptime assert(struct_layout_version == 2);
3643 var offset: u64 = 0;
3644 var big_align: u32 = 0;
3645 var need_unnamed = false;
37583646
3759 var it = struct_obj.runtimeFieldIterator();
3760 while (it.next()) |field_and_index| {
3761 const field = field_and_index.field;
3762 const field_align = field.alignment(target, struct_obj.layout);
3763 big_align = @max(big_align, field_align);
3764 const prev_offset = offset;
3765 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
3647 var it = struct_obj.runtimeFieldIterator(mod);
3648 while (it.next()) |field_and_index| {
3649 const field = field_and_index.field;
3650 const field_align = field.alignment(mod, struct_obj.layout);
3651 big_align = @max(big_align, field_align);
3652 const prev_offset = offset;
3653 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
37663654
3767 const padding_len = offset - prev_offset;
3768 if (padding_len > 0) {
3769 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3770 // TODO make this and all other padding elsewhere in debug
3771 // builds be 0xaa not undef.
3772 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3773 }
3655 const padding_len = offset - prev_offset;
3656 if (padding_len > 0) {
3657 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3658 // TODO make this and all other padding elsewhere in debug
3659 // builds be 0xaa not undef.
3660 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3661 }
37743662
3775 const field_llvm_val = try dg.lowerValue(.{
3776 .ty = field.ty,
3777 .val = field_vals[field_and_index.index],
3778 });
3663 const field_llvm_val = try dg.lowerValue(.{
3664 .ty = field.ty,
3665 .val = try tv.val.fieldValue(mod, field_and_index.index),
3666 });
37793667
3780 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
3668 need_unnamed = need_unnamed or dg.isUnnamedType(field.ty, field_llvm_val);
37813669
3782 llvm_fields.appendAssumeCapacity(field_llvm_val);
3670 llvm_fields.appendAssumeCapacity(field_llvm_val);
37833671
3784 offset += field.ty.abiSize(target);
3785 }
3786 {
3787 const prev_offset = offset;
3788 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3789 const padding_len = offset - prev_offset;
3790 if (padding_len > 0) {
3791 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3792 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3672 offset += field.ty.abiSize(mod);
3673 }
3674 {
3675 const prev_offset = offset;
3676 offset = std.mem.alignForwardGeneric(u64, offset, big_align);
3677 const padding_len = offset - prev_offset;
3678 if (padding_len > 0) {
3679 const llvm_array_ty = dg.context.intType(8).arrayType(@intCast(c_uint, padding_len));
3680 llvm_fields.appendAssumeCapacity(llvm_array_ty.getUndef());
3681 }
37933682 }
3794 }
37953683
3796 if (need_unnamed) {
3797 return dg.context.constStruct(
3798 llvm_fields.items.ptr,
3799 @intCast(c_uint, llvm_fields.items.len),
3800 .False,
3801 );
3802 } else {
3803 return llvm_struct_ty.constNamedStruct(
3804 llvm_fields.items.ptr,
3805 @intCast(c_uint, llvm_fields.items.len),
3806 );
3807 }
3684 if (need_unnamed) {
3685 return dg.context.constStruct(
3686 llvm_fields.items.ptr,
3687 @intCast(c_uint, llvm_fields.items.len),
3688 .False,
3689 );
3690 } else {
3691 return llvm_struct_ty.constNamedStruct(
3692 llvm_fields.items.ptr,
3693 @intCast(c_uint, llvm_fields.items.len),
3694 );
3695 }
3696 },
3697 else => unreachable,
38083698 },
3809 .Union => {
3699 .un => {
38103700 const llvm_union_ty = try dg.lowerType(tv.ty);
3811 const tag_and_val = tv.val.castTag(.@"union").?.data;
3701 const tag_and_val: Value.Payload.Union.Data = switch (tv.val.toIntern()) {
3702 .none => tv.val.castTag(.@"union").?.data,
3703 else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
3704 .un => |un| .{ .tag = un.tag.toValue(), .val = un.val.toValue() },
3705 else => unreachable,
3706 },
3707 };
38123708
3813 const layout = tv.ty.unionGetLayout(target);
3709 const layout = tv.ty.unionGetLayout(mod);
38143710
38153711 if (layout.payload_size == 0) {
38163712 return lowerValue(dg, .{
3817 .ty = tv.ty.unionTagTypeSafety().?,
3713 .ty = tv.ty.unionTagTypeSafety(mod).?,
38183714 .val = tag_and_val.tag,
38193715 });
38203716 }
3821 const union_obj = tv.ty.cast(Type.Payload.Union).?.data;
3717 const union_obj = mod.typeToUnion(tv.ty).?;
38223718 const field_index = tv.ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;
38233719 assert(union_obj.haveFieldTypes());
38243720
38253721 const field_ty = union_obj.fields.values()[field_index].ty;
38263722 if (union_obj.layout == .Packed) {
3827 if (!field_ty.hasRuntimeBits())
3723 if (!field_ty.hasRuntimeBits(mod))
38283724 return llvm_union_ty.constNull();
38293725 const non_int_val = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
3830 const ty_bit_size = @intCast(u16, field_ty.bitSize(target));
3726 const ty_bit_size = @intCast(u16, field_ty.bitSize(mod));
38313727 const small_int_ty = dg.context.intType(ty_bit_size);
3832 const small_int_val = if (field_ty.isPtrAtRuntime())
3728 const small_int_val = if (field_ty.isPtrAtRuntime(mod))
38333729 non_int_val.constPtrToInt(small_int_ty)
38343730 else
38353731 non_int_val.constBitCast(small_int_ty);
......@@ -3842,13 +3738,13 @@ pub const DeclGen = struct {
38423738 // must pointer cast to the expected type before accessing the union.
38433739 var need_unnamed: bool = layout.most_aligned_field != field_index;
38443740 const payload = p: {
3845 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {
3741 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
38463742 const padding_len = @intCast(c_uint, layout.payload_size);
38473743 break :p dg.context.intType(8).arrayType(padding_len).getUndef();
38483744 }
38493745 const field = try lowerValue(dg, .{ .ty = field_ty, .val = tag_and_val.val });
38503746 need_unnamed = need_unnamed or dg.isUnnamedType(field_ty, field);
3851 const field_size = field_ty.abiSize(target);
3747 const field_size = field_ty.abiSize(mod);
38523748 if (field_size == layout.payload_size) {
38533749 break :p field;
38543750 }
......@@ -3868,7 +3764,7 @@ pub const DeclGen = struct {
38683764 }
38693765 }
38703766 const llvm_tag_value = try lowerValue(dg, .{
3871 .ty = tv.ty.unionTagTypeSafety().?,
3767 .ty = tv.ty.unionTagTypeSafety(mod).?,
38723768 .val = tag_and_val.tag,
38733769 });
38743770 var fields: [3]*llvm.Value = undefined;
......@@ -3888,107 +3784,45 @@ pub const DeclGen = struct {
38883784 return llvm_union_ty.constNamedStruct(&fields, fields_len);
38893785 }
38903786 },
3891 .Vector => switch (tv.val.tag()) {
3892 .bytes => {
3893 // Note, sentinel is not stored even if the type has a sentinel.
3894 const bytes = tv.val.castTag(.bytes).?.data;
3895 const vector_len = @intCast(usize, tv.ty.arrayLen());
3896 assert(vector_len == bytes.len or vector_len + 1 == bytes.len);
3897
3898 const elem_ty = tv.ty.elemType();
3899 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3900 defer dg.gpa.free(llvm_elems);
3901 for (llvm_elems, 0..) |*elem, i| {
3902 var byte_payload: Value.Payload.U64 = .{
3903 .base = .{ .tag = .int_u64 },
3904 .data = bytes[i],
3905 };
3906
3907 elem.* = try dg.lowerValue(.{
3908 .ty = elem_ty,
3909 .val = Value.initPayload(&byte_payload.base),
3910 });
3911 }
3912 return llvm.constVector(
3913 llvm_elems.ptr,
3914 @intCast(c_uint, llvm_elems.len),
3915 );
3916 },
3917 .aggregate => {
3918 // Note, sentinel is not stored even if the type has a sentinel.
3919 // The value includes the sentinel in those cases.
3920 const elem_vals = tv.val.castTag(.aggregate).?.data;
3921 const vector_len = @intCast(usize, tv.ty.arrayLen());
3922 assert(vector_len == elem_vals.len or vector_len + 1 == elem_vals.len);
3923 const elem_ty = tv.ty.elemType();
3924 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3925 defer dg.gpa.free(llvm_elems);
3926 for (llvm_elems, 0..) |*elem, i| {
3927 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = elem_vals[i] });
3928 }
3929 return llvm.constVector(
3930 llvm_elems.ptr,
3931 @intCast(c_uint, llvm_elems.len),
3932 );
3933 },
3934 .repeated => {
3935 // Note, sentinel is not stored even if the type has a sentinel.
3936 const val = tv.val.castTag(.repeated).?.data;
3937 const elem_ty = tv.ty.elemType();
3938 const len = @intCast(usize, tv.ty.arrayLen());
3939 const llvm_elems = try dg.gpa.alloc(*llvm.Value, len);
3940 defer dg.gpa.free(llvm_elems);
3941 for (llvm_elems) |*elem| {
3942 elem.* = try dg.lowerValue(.{ .ty = elem_ty, .val = val });
3943 }
3944 return llvm.constVector(
3945 llvm_elems.ptr,
3946 @intCast(c_uint, llvm_elems.len),
3947 );
3948 },
3949 .str_lit => {
3950 // Note, sentinel is not stored
3951 const str_lit = tv.val.castTag(.str_lit).?.data;
3952 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
3953 const vector_len = @intCast(usize, tv.ty.arrayLen());
3954 assert(vector_len == bytes.len);
3955
3956 const elem_ty = tv.ty.elemType();
3957 const llvm_elems = try dg.gpa.alloc(*llvm.Value, vector_len);
3958 defer dg.gpa.free(llvm_elems);
3959 for (llvm_elems, 0..) |*elem, i| {
3960 var byte_payload: Value.Payload.U64 = .{
3961 .base = .{ .tag = .int_u64 },
3962 .data = bytes[i],
3963 };
3787 .memoized_call => unreachable,
3788 }
3789 }
39643790
3965 elem.* = try dg.lowerValue(.{
3966 .ty = elem_ty,
3967 .val = Value.initPayload(&byte_payload.base),
3968 });
3969 }
3970 return llvm.constVector(
3971 llvm_elems.ptr,
3972 @intCast(c_uint, llvm_elems.len),
3973 );
3974 },
3975 else => unreachable,
3791 fn lowerIntAsPtr(dg: *DeclGen, val: Value) Error!*llvm.Value {
3792 switch (dg.module.intern_pool.indexToKey(val.toIntern())) {
3793 .undef => return dg.context.pointerType(0).getUndef(),
3794 .int => {
3795 var bigint_space: Value.BigIntSpace = undefined;
3796 const bigint = val.toBigInt(&bigint_space, dg.module);
3797 const llvm_int = lowerBigInt(dg, Type.usize, bigint);
3798 return llvm_int.constIntToPtr(dg.context.pointerType(0));
39763799 },
3800 else => unreachable,
3801 }
3802 }
39773803
3978 .ComptimeInt => unreachable,
3979 .ComptimeFloat => unreachable,
3980 .Type => unreachable,
3981 .EnumLiteral => unreachable,
3982 .Void => unreachable,
3983 .NoReturn => unreachable,
3984 .Undefined => unreachable,
3985 .Null => unreachable,
3986 .Opaque => unreachable,
3804 fn lowerBigInt(dg: *DeclGen, ty: Type, bigint: std.math.big.int.Const) *llvm.Value {
3805 const mod = dg.module;
3806 const int_info = ty.intInfo(mod);
3807 assert(int_info.bits != 0);
3808 const llvm_type = dg.context.intType(int_info.bits);
39873809
3988 .Frame,
3989 .AnyFrame,
3990 => return dg.todo("implement const of type '{}'", .{tv.ty.fmtDebug()}),
3810 const unsigned_val = v: {
3811 if (bigint.limbs.len == 1) {
3812 break :v llvm_type.constInt(bigint.limbs[0], .False);
3813 }
3814 if (@sizeOf(usize) == @sizeOf(u64)) {
3815 break :v llvm_type.constIntOfArbitraryPrecision(
3816 @intCast(c_uint, bigint.limbs.len),
3817 bigint.limbs.ptr,
3818 );
3819 }
3820 @panic("TODO implement bigint to llvm int for 32-bit compiler builds");
3821 };
3822 if (!bigint.positive) {
3823 return llvm.constNeg(unsigned_val);
39913824 }
3825 return unsigned_val;
39923826 }
39933827
39943828 const ParentPtr = struct {
......@@ -4001,57 +3835,86 @@ pub const DeclGen = struct {
40013835 ptr_val: Value,
40023836 decl_index: Module.Decl.Index,
40033837 ) Error!*llvm.Value {
4004 const decl = dg.module.declPtr(decl_index);
4005 dg.module.markDeclAlive(decl);
4006 var ptr_ty_payload: Type.Payload.ElemType = .{
4007 .base = .{ .tag = .single_mut_pointer },
4008 .data = decl.ty,
4009 };
4010 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
3838 const mod = dg.module;
3839 const decl = mod.declPtr(decl_index);
3840 try mod.markDeclAlive(decl);
3841 const ptr_ty = try mod.singleMutPtrType(decl.ty);
40113842 return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);
40123843 }
40133844
40143845 fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value {
4015 const target = dg.module.getTarget();
4016 switch (ptr_val.tag()) {
4017 .decl_ref_mut => {
4018 const decl = ptr_val.castTag(.decl_ref_mut).?.data.decl_index;
4019 return dg.lowerParentPtrDecl(ptr_val, decl);
4020 },
4021 .decl_ref => {
4022 const decl = ptr_val.castTag(.decl_ref).?.data;
4023 return dg.lowerParentPtrDecl(ptr_val, decl);
4024 },
4025 .variable => {
4026 const decl = ptr_val.castTag(.variable).?.data.owner_decl;
4027 return dg.lowerParentPtrDecl(ptr_val, decl);
3846 const mod = dg.module;
3847 const target = mod.getTarget();
3848 return switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {
3849 .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl),
3850 .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl),
3851 .int => |int| dg.lowerIntAsPtr(int.toValue()),
3852 .eu_payload => |eu_ptr| {
3853 const parent_llvm_ptr = try dg.lowerParentPtr(eu_ptr.toValue(), true);
3854
3855 const eu_ty = mod.intern_pool.typeOf(eu_ptr).toType().childType(mod);
3856 const payload_ty = eu_ty.errorUnionPayload(mod);
3857 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
3858 // In this case, we represent pointer to error union the same as pointer
3859 // to the payload.
3860 return parent_llvm_ptr;
3861 }
3862
3863 const payload_offset: u8 = if (payload_ty.abiAlignment(mod) > Type.anyerror.abiSize(mod)) 2 else 1;
3864 const llvm_u32 = dg.context.intType(32);
3865 const indices: [2]*llvm.Value = .{
3866 llvm_u32.constInt(0, .False),
3867 llvm_u32.constInt(payload_offset, .False),
3868 };
3869 const eu_llvm_ty = try dg.lowerType(eu_ty);
3870 return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
40283871 },
4029 .int_i64 => {
4030 const int = ptr_val.castTag(.int_i64).?.data;
4031 const llvm_usize = try dg.lowerType(Type.usize);
4032 const llvm_int = llvm_usize.constInt(@bitCast(u64, int), .False);
4033 return llvm_int.constIntToPtr(dg.context.pointerType(0));
3872 .opt_payload => |opt_ptr| {
3873 const parent_llvm_ptr = try dg.lowerParentPtr(opt_ptr.toValue(), true);
3874
3875 const opt_ty = mod.intern_pool.typeOf(opt_ptr).toType().childType(mod);
3876 const payload_ty = opt_ty.optionalChild(mod);
3877 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or
3878 payload_ty.optionalReprIsPayload(mod))
3879 {
3880 // In this case, we represent pointer to optional the same as pointer
3881 // to the payload.
3882 return parent_llvm_ptr;
3883 }
3884
3885 const llvm_u32 = dg.context.intType(32);
3886 const indices: [2]*llvm.Value = .{
3887 llvm_u32.constInt(0, .False),
3888 llvm_u32.constInt(0, .False),
3889 };
3890 const opt_llvm_ty = try dg.lowerType(opt_ty);
3891 return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
40343892 },
4035 .int_u64 => {
4036 const int = ptr_val.castTag(.int_u64).?.data;
3893 .comptime_field => unreachable,
3894 .elem => |elem_ptr| {
3895 const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.base.toValue(), true);
3896
40373897 const llvm_usize = try dg.lowerType(Type.usize);
4038 const llvm_int = llvm_usize.constInt(int, .False);
4039 return llvm_int.constIntToPtr(dg.context.pointerType(0));
3898 const indices: [1]*llvm.Value = .{
3899 llvm_usize.constInt(elem_ptr.index, .False),
3900 };
3901 const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);
3902 const elem_llvm_ty = try dg.lowerType(elem_ty);
3903 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
40403904 },
4041 .field_ptr => {
4042 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
4043 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.container_ptr, byte_aligned);
4044 const parent_ty = field_ptr.container_ty;
3905 .field => |field_ptr| {
3906 const parent_llvm_ptr = try dg.lowerParentPtr(field_ptr.base.toValue(), byte_aligned);
3907 const parent_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
40453908
4046 const field_index = @intCast(u32, field_ptr.field_index);
3909 const field_index = @intCast(u32, field_ptr.index);
40473910 const llvm_u32 = dg.context.intType(32);
4048 switch (parent_ty.zigTypeTag()) {
3911 switch (parent_ty.zigTypeTag(mod)) {
40493912 .Union => {
4050 if (parent_ty.containerLayout() == .Packed) {
3913 if (parent_ty.containerLayout(mod) == .Packed) {
40513914 return parent_llvm_ptr;
40523915 }
40533916
4054 const layout = parent_ty.unionGetLayout(target);
3917 const layout = parent_ty.unionGetLayout(mod);
40553918 if (layout.payload_size == 0) {
40563919 // In this case a pointer to the union and a pointer to any
40573920 // (void) payload is the same.
......@@ -4069,16 +3932,16 @@ pub const DeclGen = struct {
40693932 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
40703933 },
40713934 .Struct => {
4072 if (parent_ty.containerLayout() == .Packed) {
3935 if (parent_ty.containerLayout(mod) == .Packed) {
40733936 if (!byte_aligned) return parent_llvm_ptr;
40743937 const llvm_usize = dg.context.intType(target.ptrBitWidth());
40753938 const base_addr = parent_llvm_ptr.constPtrToInt(llvm_usize);
40763939 // count bits of fields before this one
40773940 const prev_bits = b: {
40783941 var b: usize = 0;
4079 for (parent_ty.structFields().values()[0..field_index]) |field| {
4080 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime()) continue;
4081 b += @intCast(usize, field.ty.bitSize(target));
3942 for (parent_ty.structFields(mod).values()[0..field_index]) |field| {
3943 if (field.is_comptime or !field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
3944 b += @intCast(usize, field.ty.bitSize(mod));
40823945 }
40833946 break :b b;
40843947 };
......@@ -4088,23 +3951,21 @@ pub const DeclGen = struct {
40883951 return field_addr.constIntToPtr(final_llvm_ty);
40893952 }
40903953
4091 var ty_buf: Type.Payload.Pointer = undefined;
4092
40933954 const parent_llvm_ty = try dg.lowerType(parent_ty);
4094 if (llvmFieldIndex(parent_ty, field_index, target, &ty_buf)) |llvm_field_index| {
3955 if (llvmField(parent_ty, field_index, mod)) |llvm_field| {
40953956 const indices: [2]*llvm.Value = .{
40963957 llvm_u32.constInt(0, .False),
4097 llvm_u32.constInt(llvm_field_index, .False),
3958 llvm_u32.constInt(llvm_field.index, .False),
40983959 };
40993960 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
41003961 } else {
4101 const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime()), .False);
3962 const llvm_index = llvm_u32.constInt(@boolToInt(parent_ty.hasRuntimeBitsIgnoreComptime(mod)), .False);
41023963 const indices: [1]*llvm.Value = .{llvm_index};
41033964 return parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
41043965 }
41053966 },
41063967 .Pointer => {
4107 assert(parent_ty.isSlice());
3968 assert(parent_ty.isSlice(mod));
41083969 const indices: [2]*llvm.Value = .{
41093970 llvm_u32.constInt(0, .False),
41103971 llvm_u32.constInt(field_index, .False),
......@@ -4115,61 +3976,7 @@ pub const DeclGen = struct {
41153976 else => unreachable,
41163977 }
41173978 },
4118 .elem_ptr => {
4119 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
4120 const parent_llvm_ptr = try dg.lowerParentPtr(elem_ptr.array_ptr, true);
4121
4122 const llvm_usize = try dg.lowerType(Type.usize);
4123 const indices: [1]*llvm.Value = .{
4124 llvm_usize.constInt(elem_ptr.index, .False),
4125 };
4126 const elem_llvm_ty = try dg.lowerType(elem_ptr.elem_ty);
4127 return elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4128 },
4129 .opt_payload_ptr => {
4130 const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
4131 const parent_llvm_ptr = try dg.lowerParentPtr(opt_payload_ptr.container_ptr, true);
4132 var buf: Type.Payload.ElemType = undefined;
4133
4134 const payload_ty = opt_payload_ptr.container_ty.optionalChild(&buf);
4135 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or
4136 payload_ty.optionalReprIsPayload())
4137 {
4138 // In this case, we represent pointer to optional the same as pointer
4139 // to the payload.
4140 return parent_llvm_ptr;
4141 }
4142
4143 const llvm_u32 = dg.context.intType(32);
4144 const indices: [2]*llvm.Value = .{
4145 llvm_u32.constInt(0, .False),
4146 llvm_u32.constInt(0, .False),
4147 };
4148 const opt_llvm_ty = try dg.lowerType(opt_payload_ptr.container_ty);
4149 return opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4150 },
4151 .eu_payload_ptr => {
4152 const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
4153 const parent_llvm_ptr = try dg.lowerParentPtr(eu_payload_ptr.container_ptr, true);
4154
4155 const payload_ty = eu_payload_ptr.container_ty.errorUnionPayload();
4156 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
4157 // In this case, we represent pointer to error union the same as pointer
4158 // to the payload.
4159 return parent_llvm_ptr;
4160 }
4161
4162 const payload_offset: u8 = if (payload_ty.abiAlignment(target) > Type.anyerror.abiSize(target)) 2 else 1;
4163 const llvm_u32 = dg.context.intType(32);
4164 const indices: [2]*llvm.Value = .{
4165 llvm_u32.constInt(0, .False),
4166 llvm_u32.constInt(payload_offset, .False),
4167 };
4168 const eu_llvm_ty = try dg.lowerType(eu_payload_ptr.container_ty);
4169 return eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
4170 },
4171 else => unreachable,
4172 }
3979 };
41733980 }
41743981
41753982 fn lowerDeclRefValue(
......@@ -4177,57 +3984,39 @@ pub const DeclGen = struct {
41773984 tv: TypedValue,
41783985 decl_index: Module.Decl.Index,
41793986 ) Error!*llvm.Value {
4180 if (tv.ty.isSlice()) {
4181 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
4182 const ptr_ty = tv.ty.slicePtrFieldType(&buf);
4183 var slice_len: Value.Payload.U64 = .{
4184 .base = .{ .tag = .int_u64 },
4185 .data = tv.val.sliceLen(self.module),
4186 };
4187 const fields: [2]*llvm.Value = .{
4188 try self.lowerValue(.{
4189 .ty = ptr_ty,
4190 .val = tv.val,
4191 }),
4192 try self.lowerValue(.{
4193 .ty = Type.usize,
4194 .val = Value.initPayload(&slice_len.base),
4195 }),
4196 };
4197 return self.context.constStruct(&fields, fields.len, .False);
4198 }
3987 const mod = self.module;
41993988
42003989 // In the case of something like:
42013990 // fn foo() void {}
42023991 // const bar = foo;
42033992 // ... &bar;
42043993 // `bar` is just an alias and we actually want to lower a reference to `foo`.
4205 const decl = self.module.declPtr(decl_index);
4206 if (decl.val.castTag(.function)) |func| {
4207 if (func.data.owner_decl != decl_index) {
4208 return self.lowerDeclRefValue(tv, func.data.owner_decl);
3994 const decl = mod.declPtr(decl_index);
3995 if (decl.val.getFunction(mod)) |func| {
3996 if (func.owner_decl != decl_index) {
3997 return self.lowerDeclRefValue(tv, func.owner_decl);
42093998 }
4210 } else if (decl.val.castTag(.extern_fn)) |func| {
4211 if (func.data.owner_decl != decl_index) {
4212 return self.lowerDeclRefValue(tv, func.data.owner_decl);
3999 } else if (decl.val.getExternFunc(mod)) |func| {
4000 if (func.decl != decl_index) {
4001 return self.lowerDeclRefValue(tv, func.decl);
42134002 }
42144003 }
42154004
4216 const is_fn_body = decl.ty.zigTypeTag() == .Fn;
4217 if ((!is_fn_body and !decl.ty.hasRuntimeBits()) or
4218 (is_fn_body and decl.ty.fnInfo().is_generic))
4005 const is_fn_body = decl.ty.zigTypeTag(mod) == .Fn;
4006 if ((!is_fn_body and !decl.ty.hasRuntimeBits(mod)) or
4007 (is_fn_body and mod.typeToFunc(decl.ty).?.is_generic))
42194008 {
42204009 return self.lowerPtrToVoid(tv.ty);
42214010 }
42224011
4223 self.module.markDeclAlive(decl);
4012 try mod.markDeclAlive(decl);
42244013
42254014 const llvm_decl_val = if (is_fn_body)
42264015 try self.resolveLlvmFunction(decl_index)
42274016 else
42284017 try self.resolveGlobalDecl(decl_index);
42294018
4230 const target = self.module.getTarget();
4019 const target = mod.getTarget();
42314020 const llvm_wanted_addrspace = toLlvmAddressSpace(decl.@"addrspace", target);
42324021 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(decl.@"addrspace", target);
42334022 const llvm_val = if (llvm_wanted_addrspace != llvm_actual_addrspace) blk: {
......@@ -4236,7 +4025,7 @@ pub const DeclGen = struct {
42364025 } else llvm_decl_val;
42374026
42384027 const llvm_type = try self.lowerType(tv.ty);
4239 if (tv.ty.zigTypeTag() == .Int) {
4028 if (tv.ty.zigTypeTag(mod) == .Int) {
42404029 return llvm_val.constPtrToInt(llvm_type);
42414030 } else {
42424031 return llvm_val.constBitCast(llvm_type);
......@@ -4244,7 +4033,8 @@ pub const DeclGen = struct {
42444033 }
42454034
42464035 fn lowerPtrToVoid(dg: *DeclGen, ptr_ty: Type) !*llvm.Value {
4247 const alignment = ptr_ty.ptrInfo().data.@"align";
4036 const mod = dg.module;
4037 const alignment = ptr_ty.ptrInfo(mod).@"align";
42484038 // Even though we are pointing at something which has zero bits (e.g. `void`),
42494039 // Pointers are defined to have bits. So we must return something here.
42504040 // The value cannot be undefined, because we use the `nonnull` annotation
......@@ -4338,21 +4128,20 @@ pub const DeclGen = struct {
43384128 /// RMW exchange of floating-point values is bitcasted to same-sized integer
43394129 /// types to work around a LLVM deficiency when targeting ARM/AArch64.
43404130 fn getAtomicAbiType(dg: *DeclGen, ty: Type, is_rmw_xchg: bool) ?*llvm.Type {
4341 const target = dg.module.getTarget();
4342 var buffer: Type.Payload.Bits = undefined;
4343 const int_ty = switch (ty.zigTypeTag()) {
4131 const mod = dg.module;
4132 const int_ty = switch (ty.zigTypeTag(mod)) {
43444133 .Int => ty,
4345 .Enum => ty.intTagType(&buffer),
4134 .Enum => ty.intTagType(mod),
43464135 .Float => {
43474136 if (!is_rmw_xchg) return null;
4348 return dg.context.intType(@intCast(c_uint, ty.abiSize(target) * 8));
4137 return dg.context.intType(@intCast(c_uint, ty.abiSize(mod) * 8));
43494138 },
43504139 .Bool => return dg.context.intType(8),
43514140 else => return null,
43524141 };
4353 const bit_count = int_ty.intInfo(target).bits;
4142 const bit_count = int_ty.intInfo(mod).bits;
43544143 if (!std.math.isPowerOfTwo(bit_count) or (bit_count % 8) != 0) {
4355 return dg.context.intType(@intCast(c_uint, int_ty.abiSize(target) * 8));
4144 return dg.context.intType(@intCast(c_uint, int_ty.abiSize(mod) * 8));
43564145 } else {
43574146 return null;
43584147 }
......@@ -4363,18 +4152,18 @@ pub const DeclGen = struct {
43634152 llvm_fn: *llvm.Value,
43644153 param_ty: Type,
43654154 param_index: u32,
4366 fn_info: Type.Payload.Function.Data,
4155 fn_info: InternPool.Key.FuncType,
43674156 llvm_arg_i: u32,
43684157 ) void {
4369 const target = dg.module.getTarget();
4370 if (param_ty.isPtrAtRuntime()) {
4371 const ptr_info = param_ty.ptrInfo().data;
4158 const mod = dg.module;
4159 if (param_ty.isPtrAtRuntime(mod)) {
4160 const ptr_info = param_ty.ptrInfo(mod);
43724161 if (math.cast(u5, param_index)) |i| {
43734162 if (@truncate(u1, fn_info.noalias_bits >> i) != 0) {
43744163 dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias");
43754164 }
43764165 }
4377 if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") {
4166 if (!param_ty.isPtrLikeOptional(mod) and !ptr_info.@"allowzero") {
43784167 dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull");
43794168 }
43804169 if (!ptr_info.mutable) {
......@@ -4383,13 +4172,10 @@ pub const DeclGen = struct {
43834172 if (ptr_info.@"align" != 0) {
43844173 dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align");
43854174 } else {
4386 const elem_align = @max(
4387 ptr_info.pointee_type.abiAlignment(target),
4388 1,
4389 );
4175 const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1);
43904176 dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align);
43914177 }
4392 } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) {
4178 } else if (ccAbiPromoteInt(fn_info.cc, mod, param_ty)) |s| switch (s) {
43934179 .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"),
43944180 .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"),
43954181 };
......@@ -4490,21 +4276,23 @@ pub const FuncGen = struct {
44904276 const gop = try self.func_inst_table.getOrPut(self.dg.gpa, inst);
44914277 if (gop.found_existing) return gop.value_ptr.*;
44924278
4279 const mod = self.dg.module;
44934280 const llvm_val = try self.resolveValue(.{
4494 .ty = self.air.typeOf(inst),
4495 .val = self.air.value(inst).?,
4281 .ty = self.typeOf(inst),
4282 .val = (try self.air.value(inst, mod)).?,
44964283 });
44974284 gop.value_ptr.* = llvm_val;
44984285 return llvm_val;
44994286 }
45004287
45014288 fn resolveValue(self: *FuncGen, tv: TypedValue) !*llvm.Value {
4289 const mod = self.dg.module;
45024290 const llvm_val = try self.dg.lowerValue(tv);
4503 if (!isByRef(tv.ty)) return llvm_val;
4291 if (!isByRef(tv.ty, mod)) return llvm_val;
45044292
45054293 // We have an LLVM value but we need to create a global constant and
45064294 // set the value as its initializer, and then return a pointer to the global.
4507 const target = self.dg.module.getTarget();
4295 const target = mod.getTarget();
45084296 const llvm_wanted_addrspace = toLlvmAddressSpace(.generic, target);
45094297 const llvm_actual_addrspace = toLlvmGlobalAddressSpace(.generic, target);
45104298 const global = self.dg.object.llvm_module.addGlobalInAddressSpace(llvm_val.typeOf(), "", llvm_actual_addrspace);
......@@ -4512,7 +4300,7 @@ pub const FuncGen = struct {
45124300 global.setLinkage(.Private);
45134301 global.setGlobalConstant(.True);
45144302 global.setUnnamedAddr(.True);
4515 global.setAlignment(tv.ty.abiAlignment(target));
4303 global.setAlignment(tv.ty.abiAlignment(mod));
45164304 const addrspace_casted_ptr = if (llvm_actual_addrspace != llvm_wanted_addrspace)
45174305 global.constAddrSpaceCast(self.context.pointerType(llvm_wanted_addrspace))
45184306 else
......@@ -4521,11 +4309,12 @@ pub const FuncGen = struct {
45214309 }
45224310
45234311 fn genBody(self: *FuncGen, body: []const Air.Inst.Index) Error!void {
4312 const mod = self.dg.module;
4313 const ip = &mod.intern_pool;
45244314 const air_tags = self.air.instructions.items(.tag);
45254315 for (body, 0..) |inst, i| {
4526 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
4316 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
45274317 continue;
4528 }
45294318
45304319 const opt_value: ?*llvm.Value = switch (air_tags[inst]) {
45314320 // zig fmt: off
......@@ -4742,8 +4531,8 @@ pub const FuncGen = struct {
47424531
47434532 .vector_store_elem => try self.airVectorStoreElem(inst),
47444533
4745 .constant => unreachable,
4746 .const_ty => unreachable,
4534 .inferred_alloc, .inferred_alloc_comptime, .interned => unreachable,
4535
47474536 .unreach => self.airUnreach(inst),
47484537 .dbg_stmt => self.airDbgStmt(inst),
47494538 .dbg_inline_begin => try self.airDbgInlineBegin(inst),
......@@ -4774,29 +4563,30 @@ pub const FuncGen = struct {
47744563 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
47754564 const extra = self.air.extraData(Air.Call, pl_op.payload);
47764565 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
4777 const callee_ty = self.air.typeOf(pl_op.operand);
4778 const zig_fn_ty = switch (callee_ty.zigTypeTag()) {
4566 const mod = self.dg.module;
4567 const callee_ty = self.typeOf(pl_op.operand);
4568 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
47794569 .Fn => callee_ty,
4780 .Pointer => callee_ty.childType(),
4570 .Pointer => callee_ty.childType(mod),
47814571 else => unreachable,
47824572 };
4783 const fn_info = zig_fn_ty.fnInfo();
4784 const return_type = fn_info.return_type;
4573 const fn_info = mod.typeToFunc(zig_fn_ty).?;
4574 const return_type = fn_info.return_type.toType();
47854575 const llvm_fn = try self.resolveInst(pl_op.operand);
4786 const target = self.dg.module.getTarget();
4787 const sret = firstParamSRet(fn_info, target);
4576 const target = mod.getTarget();
4577 const sret = firstParamSRet(fn_info, mod);
47884578
47894579 var llvm_args = std.ArrayList(*llvm.Value).init(self.gpa);
47904580 defer llvm_args.deinit();
47914581
47924582 const ret_ptr = if (!sret) null else blk: {
47934583 const llvm_ret_ty = try self.dg.lowerType(return_type);
4794 const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(target));
4584 const ret_ptr = self.buildAlloca(llvm_ret_ty, return_type.abiAlignment(mod));
47954585 try llvm_args.append(ret_ptr);
47964586 break :blk ret_ptr;
47974587 };
47984588
4799 const err_return_tracing = fn_info.return_type.isError() and
4589 const err_return_tracing = return_type.isError(mod) and
48004590 self.dg.module.comp.bin_file.options.error_return_tracing;
48014591 if (err_return_tracing) {
48024592 try llvm_args.append(self.err_ret_trace.?);
......@@ -4807,11 +4597,11 @@ pub const FuncGen = struct {
48074597 .no_bits => continue,
48084598 .byval => {
48094599 const arg = args[it.zig_index - 1];
4810 const param_ty = self.air.typeOf(arg);
4600 const param_ty = self.typeOf(arg);
48114601 const llvm_arg = try self.resolveInst(arg);
48124602 const llvm_param_ty = try self.dg.lowerType(param_ty);
4813 if (isByRef(param_ty)) {
4814 const alignment = param_ty.abiAlignment(target);
4603 if (isByRef(param_ty, mod)) {
4604 const alignment = param_ty.abiAlignment(mod);
48154605 const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, "");
48164606 load_inst.setAlignment(alignment);
48174607 try llvm_args.append(load_inst);
......@@ -4821,12 +4611,12 @@ pub const FuncGen = struct {
48214611 },
48224612 .byref => {
48234613 const arg = args[it.zig_index - 1];
4824 const param_ty = self.air.typeOf(arg);
4614 const param_ty = self.typeOf(arg);
48254615 const llvm_arg = try self.resolveInst(arg);
4826 if (isByRef(param_ty)) {
4616 if (isByRef(param_ty, mod)) {
48274617 try llvm_args.append(llvm_arg);
48284618 } else {
4829 const alignment = param_ty.abiAlignment(target);
4619 const alignment = param_ty.abiAlignment(mod);
48304620 const param_llvm_ty = llvm_arg.typeOf();
48314621 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);
48324622 const store_inst = self.builder.buildStore(llvm_arg, arg_ptr);
......@@ -4836,13 +4626,13 @@ pub const FuncGen = struct {
48364626 },
48374627 .byref_mut => {
48384628 const arg = args[it.zig_index - 1];
4839 const param_ty = self.air.typeOf(arg);
4629 const param_ty = self.typeOf(arg);
48404630 const llvm_arg = try self.resolveInst(arg);
48414631
4842 const alignment = param_ty.abiAlignment(target);
4632 const alignment = param_ty.abiAlignment(mod);
48434633 const param_llvm_ty = try self.dg.lowerType(param_ty);
48444634 const arg_ptr = self.buildAlloca(param_llvm_ty, alignment);
4845 if (isByRef(param_ty)) {
4635 if (isByRef(param_ty, mod)) {
48464636 const load_inst = self.builder.buildLoad(param_llvm_ty, llvm_arg, "");
48474637 load_inst.setAlignment(alignment);
48484638
......@@ -4857,13 +4647,13 @@ pub const FuncGen = struct {
48574647 },
48584648 .abi_sized_int => {
48594649 const arg = args[it.zig_index - 1];
4860 const param_ty = self.air.typeOf(arg);
4650 const param_ty = self.typeOf(arg);
48614651 const llvm_arg = try self.resolveInst(arg);
4862 const abi_size = @intCast(c_uint, param_ty.abiSize(target));
4652 const abi_size = @intCast(c_uint, param_ty.abiSize(mod));
48634653 const int_llvm_ty = self.context.intType(abi_size * 8);
48644654
4865 if (isByRef(param_ty)) {
4866 const alignment = param_ty.abiAlignment(target);
4655 if (isByRef(param_ty, mod)) {
4656 const alignment = param_ty.abiAlignment(mod);
48674657 const load_inst = self.builder.buildLoad(int_llvm_ty, llvm_arg, "");
48684658 load_inst.setAlignment(alignment);
48694659 try llvm_args.append(load_inst);
......@@ -4871,7 +4661,7 @@ pub const FuncGen = struct {
48714661 // LLVM does not allow bitcasting structs so we must allocate
48724662 // a local, store as one type, and then load as another type.
48734663 const alignment = @max(
4874 param_ty.abiAlignment(target),
4664 param_ty.abiAlignment(mod),
48754665 self.dg.object.target_data.abiAlignmentOfType(int_llvm_ty),
48764666 );
48774667 const int_ptr = self.buildAlloca(int_llvm_ty, alignment);
......@@ -4893,14 +4683,14 @@ pub const FuncGen = struct {
48934683 },
48944684 .multiple_llvm_types => {
48954685 const arg = args[it.zig_index - 1];
4896 const param_ty = self.air.typeOf(arg);
4686 const param_ty = self.typeOf(arg);
48974687 const llvm_types = it.llvm_types_buffer[0..it.llvm_types_len];
48984688 const llvm_arg = try self.resolveInst(arg);
4899 const is_by_ref = isByRef(param_ty);
4689 const is_by_ref = isByRef(param_ty, mod);
49004690 const arg_ptr = if (is_by_ref) llvm_arg else p: {
49014691 const p = self.buildAlloca(llvm_arg.typeOf(), null);
49024692 const store_inst = self.builder.buildStore(llvm_arg, p);
4903 store_inst.setAlignment(param_ty.abiAlignment(target));
4693 store_inst.setAlignment(param_ty.abiAlignment(mod));
49044694 break :p p;
49054695 };
49064696
......@@ -4922,19 +4712,19 @@ pub const FuncGen = struct {
49224712 },
49234713 .float_array => |count| {
49244714 const arg = args[it.zig_index - 1];
4925 const arg_ty = self.air.typeOf(arg);
4715 const arg_ty = self.typeOf(arg);
49264716 var llvm_arg = try self.resolveInst(arg);
4927 if (!isByRef(arg_ty)) {
4717 if (!isByRef(arg_ty, mod)) {
49284718 const p = self.buildAlloca(llvm_arg.typeOf(), null);
49294719 const store_inst = self.builder.buildStore(llvm_arg, p);
4930 store_inst.setAlignment(arg_ty.abiAlignment(target));
4720 store_inst.setAlignment(arg_ty.abiAlignment(mod));
49314721 llvm_arg = store_inst;
49324722 }
49334723
4934 const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty).?);
4724 const float_ty = try self.dg.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, mod).?);
49354725 const array_llvm_ty = float_ty.arrayType(count);
49364726
4937 const alignment = arg_ty.abiAlignment(target);
4727 const alignment = arg_ty.abiAlignment(mod);
49384728 const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, "");
49394729 load_inst.setAlignment(alignment);
49404730 try llvm_args.append(load_inst);
......@@ -4942,17 +4732,17 @@ pub const FuncGen = struct {
49424732 .i32_array, .i64_array => |arr_len| {
49434733 const elem_size: u8 = if (lowering == .i32_array) 32 else 64;
49444734 const arg = args[it.zig_index - 1];
4945 const arg_ty = self.air.typeOf(arg);
4735 const arg_ty = self.typeOf(arg);
49464736 var llvm_arg = try self.resolveInst(arg);
4947 if (!isByRef(arg_ty)) {
4737 if (!isByRef(arg_ty, mod)) {
49484738 const p = self.buildAlloca(llvm_arg.typeOf(), null);
49494739 const store_inst = self.builder.buildStore(llvm_arg, p);
4950 store_inst.setAlignment(arg_ty.abiAlignment(target));
4740 store_inst.setAlignment(arg_ty.abiAlignment(mod));
49514741 llvm_arg = store_inst;
49524742 }
49534743
49544744 const array_llvm_ty = self.context.intType(elem_size).arrayType(arr_len);
4955 const alignment = arg_ty.abiAlignment(target);
4745 const alignment = arg_ty.abiAlignment(mod);
49564746 const load_inst = self.builder.buildLoad(array_llvm_ty, llvm_arg, "");
49574747 load_inst.setAlignment(alignment);
49584748 try llvm_args.append(load_inst);
......@@ -4969,7 +4759,7 @@ pub const FuncGen = struct {
49694759 "",
49704760 );
49714761
4972 if (callee_ty.zigTypeTag() == .Pointer) {
4762 if (callee_ty.zigTypeTag(mod) == .Pointer) {
49734763 // Add argument attributes for function pointer calls.
49744764 it = iterateParamTypes(self.dg, fn_info);
49754765 it.llvm_index += @boolToInt(sret);
......@@ -4977,16 +4767,16 @@ pub const FuncGen = struct {
49774767 while (it.next()) |lowering| switch (lowering) {
49784768 .byval => {
49794769 const param_index = it.zig_index - 1;
4980 const param_ty = fn_info.param_types[param_index];
4981 if (!isByRef(param_ty)) {
4770 const param_ty = fn_info.param_types[param_index].toType();
4771 if (!isByRef(param_ty, mod)) {
49824772 self.dg.addByValParamAttrs(call, param_ty, param_index, fn_info, it.llvm_index - 1);
49834773 }
49844774 },
49854775 .byref => {
49864776 const param_index = it.zig_index - 1;
4987 const param_ty = fn_info.param_types[param_index];
4777 const param_ty = fn_info.param_types[param_index].toType();
49884778 const param_llvm_ty = try self.dg.lowerType(param_ty);
4989 const alignment = param_ty.abiAlignment(target);
4779 const alignment = param_ty.abiAlignment(mod);
49904780 self.dg.addByRefParamAttrs(call, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty);
49914781 },
49924782 .byref_mut => {
......@@ -5004,8 +4794,8 @@ pub const FuncGen = struct {
50044794
50054795 .slice => {
50064796 assert(!it.byval_attr);
5007 const param_ty = fn_info.param_types[it.zig_index - 1];
5008 const ptr_info = param_ty.ptrInfo().data;
4797 const param_ty = fn_info.param_types[it.zig_index - 1].toType();
4798 const ptr_info = param_ty.ptrInfo(mod);
50094799 const llvm_arg_i = it.llvm_index - 2;
50104800
50114801 if (math.cast(u5, it.zig_index - 1)) |i| {
......@@ -5013,7 +4803,7 @@ pub const FuncGen = struct {
50134803 self.dg.addArgAttr(call, llvm_arg_i, "noalias");
50144804 }
50154805 }
5016 if (param_ty.zigTypeTag() != .Optional) {
4806 if (param_ty.zigTypeTag(mod) != .Optional) {
50174807 self.dg.addArgAttr(call, llvm_arg_i, "nonnull");
50184808 }
50194809 if (!ptr_info.mutable) {
......@@ -5022,18 +4812,18 @@ pub const FuncGen = struct {
50224812 if (ptr_info.@"align" != 0) {
50234813 self.dg.addArgAttrInt(call, llvm_arg_i, "align", ptr_info.@"align");
50244814 } else {
5025 const elem_align = @max(ptr_info.pointee_type.abiAlignment(target), 1);
4815 const elem_align = @max(ptr_info.pointee_type.abiAlignment(mod), 1);
50264816 self.dg.addArgAttrInt(call, llvm_arg_i, "align", elem_align);
50274817 }
50284818 },
50294819 };
50304820 }
50314821
5032 if (return_type.isNoReturn() and attr != .AlwaysTail) {
4822 if (fn_info.return_type == .noreturn_type and attr != .AlwaysTail) {
50334823 return null;
50344824 }
50354825
5036 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) {
4826 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime(mod)) {
50374827 return null;
50384828 }
50394829
......@@ -5041,12 +4831,12 @@ pub const FuncGen = struct {
50414831
50424832 if (ret_ptr) |rp| {
50434833 call.setCallSret(llvm_ret_ty);
5044 if (isByRef(return_type)) {
4834 if (isByRef(return_type, mod)) {
50454835 return rp;
50464836 } else {
50474837 // our by-ref status disagrees with sret so we must load.
50484838 const loaded = self.builder.buildLoad(llvm_ret_ty, rp, "");
5049 loaded.setAlignment(return_type.abiAlignment(target));
4839 loaded.setAlignment(return_type.abiAlignment(mod));
50504840 return loaded;
50514841 }
50524842 }
......@@ -5061,7 +4851,7 @@ pub const FuncGen = struct {
50614851 const rp = self.buildAlloca(llvm_ret_ty, alignment);
50624852 const store_inst = self.builder.buildStore(call, rp);
50634853 store_inst.setAlignment(alignment);
5064 if (isByRef(return_type)) {
4854 if (isByRef(return_type, mod)) {
50654855 return rp;
50664856 } else {
50674857 const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, "");
......@@ -5070,10 +4860,10 @@ pub const FuncGen = struct {
50704860 }
50714861 }
50724862
5073 if (isByRef(return_type)) {
4863 if (isByRef(return_type, mod)) {
50744864 // our by-ref status disagrees with sret so we must allocate, store,
50754865 // and return the allocation pointer.
5076 const alignment = return_type.abiAlignment(target);
4866 const alignment = return_type.abiAlignment(mod);
50774867 const rp = self.buildAlloca(llvm_ret_ty, alignment);
50784868 const store_inst = self.builder.buildStore(call, rp);
50794869 store_inst.setAlignment(alignment);
......@@ -5084,22 +4874,19 @@ pub const FuncGen = struct {
50844874 }
50854875
50864876 fn airRet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4877 const mod = self.dg.module;
50874878 const un_op = self.air.instructions.items(.data)[inst].un_op;
5088 const ret_ty = self.air.typeOf(un_op);
4879 const ret_ty = self.typeOf(un_op);
50894880 if (self.ret_ptr) |ret_ptr| {
50904881 const operand = try self.resolveInst(un_op);
5091 var ptr_ty_payload: Type.Payload.ElemType = .{
5092 .base = .{ .tag = .single_mut_pointer },
5093 .data = ret_ty,
5094 };
5095 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
4882 const ptr_ty = try mod.singleMutPtrType(ret_ty);
50964883 try self.store(ret_ptr, ptr_ty, operand, .NotAtomic);
50974884 _ = self.builder.buildRetVoid();
50984885 return null;
50994886 }
5100 const fn_info = self.dg.decl.ty.fnInfo();
5101 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
5102 if (fn_info.return_type.isError()) {
4887 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
4888 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4889 if (fn_info.return_type.toType().isError(mod)) {
51034890 // Functions with an empty error set are emitted with an error code
51044891 // return type and return zero so they can be function pointers coerced
51054892 // to functions that return anyerror.
......@@ -5113,10 +4900,9 @@ pub const FuncGen = struct {
51134900
51144901 const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);
51154902 const operand = try self.resolveInst(un_op);
5116 const target = self.dg.module.getTarget();
5117 const alignment = ret_ty.abiAlignment(target);
4903 const alignment = ret_ty.abiAlignment(mod);
51184904
5119 if (isByRef(ret_ty)) {
4905 if (isByRef(ret_ty, mod)) {
51204906 // operand is a pointer however self.ret_ptr is null so that means
51214907 // we need to return a value.
51224908 const load_inst = self.builder.buildLoad(abi_ret_ty, operand, "");
......@@ -5141,12 +4927,13 @@ pub const FuncGen = struct {
51414927 }
51424928
51434929 fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
4930 const mod = self.dg.module;
51444931 const un_op = self.air.instructions.items(.data)[inst].un_op;
5145 const ptr_ty = self.air.typeOf(un_op);
5146 const ret_ty = ptr_ty.childType();
5147 const fn_info = self.dg.decl.ty.fnInfo();
5148 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
5149 if (fn_info.return_type.isError()) {
4932 const ptr_ty = self.typeOf(un_op);
4933 const ret_ty = ptr_ty.childType(mod);
4934 const fn_info = mod.typeToFunc(self.dg.decl.ty).?;
4935 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
4936 if (fn_info.return_type.toType().isError(mod)) {
51504937 // Functions with an empty error set are emitted with an error code
51514938 // return type and return zero so they can be function pointers coerced
51524939 // to functions that return anyerror.
......@@ -5162,10 +4949,9 @@ pub const FuncGen = struct {
51624949 return null;
51634950 }
51644951 const ptr = try self.resolveInst(un_op);
5165 const target = self.dg.module.getTarget();
51664952 const abi_ret_ty = try lowerFnRetTy(self.dg, fn_info);
51674953 const loaded = self.builder.buildLoad(abi_ret_ty, ptr, "");
5168 loaded.setAlignment(ret_ty.abiAlignment(target));
4954 loaded.setAlignment(ret_ty.abiAlignment(mod));
51694955 _ = self.builder.buildRet(loaded);
51704956 return null;
51714957 }
......@@ -5184,9 +4970,9 @@ pub const FuncGen = struct {
51844970 const src_list = try self.resolveInst(ty_op.operand);
51854971 const va_list_ty = self.air.getRefType(ty_op.ty);
51864972 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);
4973 const mod = self.dg.module;
51874974
5188 const target = self.dg.module.getTarget();
5189 const result_alignment = va_list_ty.abiAlignment(target);
4975 const result_alignment = va_list_ty.abiAlignment(mod);
51904976 const dest_list = self.buildAlloca(llvm_va_list_ty, result_alignment);
51914977
51924978 const llvm_fn_name = "llvm.va_copy";
......@@ -5202,7 +4988,7 @@ pub const FuncGen = struct {
52024988 const args: [2]*llvm.Value = .{ dest_list, src_list };
52034989 _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");
52044990
5205 if (isByRef(va_list_ty)) {
4991 if (isByRef(va_list_ty, mod)) {
52064992 return dest_list;
52074993 } else {
52084994 const loaded = self.builder.buildLoad(llvm_va_list_ty, dest_list, "");
......@@ -5227,11 +5013,11 @@ pub const FuncGen = struct {
52275013 }
52285014
52295015 fn airCVaStart(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5230 const va_list_ty = self.air.typeOfIndex(inst);
5016 const mod = self.dg.module;
5017 const va_list_ty = self.typeOfIndex(inst);
52315018 const llvm_va_list_ty = try self.dg.lowerType(va_list_ty);
52325019
5233 const target = self.dg.module.getTarget();
5234 const result_alignment = va_list_ty.abiAlignment(target);
5020 const result_alignment = va_list_ty.abiAlignment(mod);
52355021 const list = self.buildAlloca(llvm_va_list_ty, result_alignment);
52365022
52375023 const llvm_fn_name = "llvm.va_start";
......@@ -5243,7 +5029,7 @@ pub const FuncGen = struct {
52435029 const args: [1]*llvm.Value = .{list};
52445030 _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, "");
52455031
5246 if (isByRef(va_list_ty)) {
5032 if (isByRef(va_list_ty, mod)) {
52475033 return list;
52485034 } else {
52495035 const loaded = self.builder.buildLoad(llvm_va_list_ty, list, "");
......@@ -5258,7 +5044,7 @@ pub const FuncGen = struct {
52585044 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
52595045 const lhs = try self.resolveInst(bin_op.lhs);
52605046 const rhs = try self.resolveInst(bin_op.rhs);
5261 const operand_ty = self.air.typeOf(bin_op.lhs);
5047 const operand_ty = self.typeOf(bin_op.lhs);
52625048
52635049 return self.cmp(lhs, rhs, operand_ty, op);
52645050 }
......@@ -5271,7 +5057,7 @@ pub const FuncGen = struct {
52715057
52725058 const lhs = try self.resolveInst(extra.lhs);
52735059 const rhs = try self.resolveInst(extra.rhs);
5274 const vec_ty = self.air.typeOf(extra.lhs);
5060 const vec_ty = self.typeOf(extra.lhs);
52755061 const cmp_op = extra.compareOperator();
52765062
52775063 return self.cmp(lhs, rhs, vec_ty, cmp_op);
......@@ -5292,23 +5078,21 @@ pub const FuncGen = struct {
52925078 operand_ty: Type,
52935079 op: math.CompareOperator,
52945080 ) Allocator.Error!*llvm.Value {
5295 var int_buffer: Type.Payload.Bits = undefined;
5296 var opt_buffer: Type.Payload.ElemType = undefined;
5297
5298 const scalar_ty = operand_ty.scalarType();
5299 const int_ty = switch (scalar_ty.zigTypeTag()) {
5300 .Enum => scalar_ty.intTagType(&int_buffer),
5081 const mod = self.dg.module;
5082 const scalar_ty = operand_ty.scalarType(mod);
5083 const int_ty = switch (scalar_ty.zigTypeTag(mod)) {
5084 .Enum => scalar_ty.intTagType(mod),
53015085 .Int, .Bool, .Pointer, .ErrorSet => scalar_ty,
53025086 .Optional => blk: {
5303 const payload_ty = operand_ty.optionalChild(&opt_buffer);
5304 if (!payload_ty.hasRuntimeBitsIgnoreComptime() or
5305 operand_ty.optionalReprIsPayload())
5087 const payload_ty = operand_ty.optionalChild(mod);
5088 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod) or
5089 operand_ty.optionalReprIsPayload(mod))
53065090 {
53075091 break :blk operand_ty;
53085092 }
53095093 // We need to emit instructions to check for equality/inequality
53105094 // of optionals that are not pointers.
5311 const is_by_ref = isByRef(scalar_ty);
5095 const is_by_ref = isByRef(scalar_ty, mod);
53125096 const opt_llvm_ty = try self.dg.lowerType(scalar_ty);
53135097 const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref);
53145098 const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref);
......@@ -5375,7 +5159,7 @@ pub const FuncGen = struct {
53755159 .Float => return self.buildFloatCmp(op, operand_ty, .{ lhs, rhs }),
53765160 else => unreachable,
53775161 };
5378 const is_signed = int_ty.isSignedInt();
5162 const is_signed = int_ty.isSignedInt(mod);
53795163 const operation: llvm.IntPredicate = switch (op) {
53805164 .eq => .EQ,
53815165 .neq => .NE,
......@@ -5388,13 +5172,14 @@ pub const FuncGen = struct {
53885172 }
53895173
53905174 fn airBlock(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5175 const mod = self.dg.module;
53915176 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
53925177 const extra = self.air.extraData(Air.Block, ty_pl.payload);
53935178 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5394 const inst_ty = self.air.typeOfIndex(inst);
5179 const inst_ty = self.typeOfIndex(inst);
53955180 const parent_bb = self.context.createBasicBlock("Block");
53965181
5397 if (inst_ty.isNoReturn()) {
5182 if (inst_ty.isNoReturn(mod)) {
53985183 try self.genBody(body);
53995184 return null;
54005185 }
......@@ -5414,8 +5199,8 @@ pub const FuncGen = struct {
54145199 self.builder.positionBuilderAtEnd(parent_bb);
54155200
54165201 // Create a phi node only if the block returns a value.
5417 const is_body = inst_ty.zigTypeTag() == .Fn;
5418 if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime()) return null;
5202 const is_body = inst_ty.zigTypeTag(mod) == .Fn;
5203 if (!is_body and !inst_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
54195204
54205205 const raw_llvm_ty = try self.dg.lowerType(inst_ty);
54215206
......@@ -5424,7 +5209,7 @@ pub const FuncGen = struct {
54245209 // a pointer to it. LLVM IR allows the call instruction to use function bodies instead
54255210 // of function pointers, however the phi makes it a runtime value and therefore
54265211 // the LLVM type has to be wrapped in a pointer.
5427 if (is_body or isByRef(inst_ty)) {
5212 if (is_body or isByRef(inst_ty, mod)) {
54285213 break :ty self.context.pointerType(0);
54295214 }
54305215 break :ty raw_llvm_ty;
......@@ -5444,8 +5229,9 @@ pub const FuncGen = struct {
54445229 const block = self.blocks.get(branch.block_inst).?;
54455230
54465231 // Add the values to the lists only if the break provides a value.
5447 const operand_ty = self.air.typeOf(branch.operand);
5448 if (operand_ty.hasRuntimeBitsIgnoreComptime() or operand_ty.zigTypeTag() == .Fn) {
5232 const operand_ty = self.typeOf(branch.operand);
5233 const mod = self.dg.module;
5234 if (operand_ty.hasRuntimeBitsIgnoreComptime(mod) or operand_ty.zigTypeTag(mod) == .Fn) {
54495235 const val = try self.resolveInst(branch.operand);
54505236
54515237 // For the phi node, we need the basic blocks and the values of the
......@@ -5481,24 +5267,26 @@ pub const FuncGen = struct {
54815267 }
54825268
54835269 fn airTry(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5270 const mod = self.dg.module;
54845271 const inst = body_tail[0];
54855272 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
54865273 const err_union = try self.resolveInst(pl_op.operand);
54875274 const extra = self.air.extraData(Air.Try, pl_op.payload);
54885275 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5489 const err_union_ty = self.air.typeOf(pl_op.operand);
5490 const payload_ty = self.air.typeOfIndex(inst);
5491 const can_elide_load = if (isByRef(payload_ty)) self.canElideLoad(body_tail) else false;
5276 const err_union_ty = self.typeOf(pl_op.operand);
5277 const payload_ty = self.typeOfIndex(inst);
5278 const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false;
54925279 const is_unused = self.liveness.isUnused(inst);
54935280 return lowerTry(self, err_union, body, err_union_ty, false, can_elide_load, is_unused);
54945281 }
54955282
54965283 fn airTryPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5284 const mod = self.dg.module;
54975285 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
54985286 const extra = self.air.extraData(Air.TryPtr, ty_pl.payload);
54995287 const err_union_ptr = try self.resolveInst(extra.data.ptr);
55005288 const body = self.air.extra[extra.end..][0..extra.data.body_len];
5501 const err_union_ty = self.air.typeOf(extra.data.ptr).childType();
5289 const err_union_ty = self.typeOf(extra.data.ptr).childType(mod);
55025290 const is_unused = self.liveness.isUnused(inst);
55035291 return lowerTry(self, err_union_ptr, body, err_union_ty, true, true, is_unused);
55045292 }
......@@ -5512,12 +5300,12 @@ pub const FuncGen = struct {
55125300 can_elide_load: bool,
55135301 is_unused: bool,
55145302 ) !?*llvm.Value {
5515 const payload_ty = err_union_ty.errorUnionPayload();
5516 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime();
5517 const target = fg.dg.module.getTarget();
5303 const mod = fg.dg.module;
5304 const payload_ty = err_union_ty.errorUnionPayload(mod);
5305 const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod);
55185306 const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty);
55195307
5520 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
5308 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
55215309 const is_err = err: {
55225310 const err_set_ty = try fg.dg.lowerType(Type.anyerror);
55235311 const zero = err_set_ty.constNull();
......@@ -5529,8 +5317,8 @@ pub const FuncGen = struct {
55295317 err_union;
55305318 break :err fg.builder.buildICmp(.NE, loaded, zero, "");
55315319 }
5532 const err_field_index = errUnionErrorOffset(payload_ty, target);
5533 if (operand_is_ptr or isByRef(err_union_ty)) {
5320 const err_field_index = errUnionErrorOffset(payload_ty, mod);
5321 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
55345322 const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, "");
55355323 // TODO add alignment to this load
55365324 const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, "");
......@@ -5555,30 +5343,31 @@ pub const FuncGen = struct {
55555343 if (!payload_has_bits) {
55565344 return if (operand_is_ptr) err_union else null;
55575345 }
5558 const offset = errUnionPayloadOffset(payload_ty, target);
5346 const offset = errUnionPayloadOffset(payload_ty, mod);
55595347 if (operand_is_ptr) {
55605348 return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, "");
5561 } else if (isByRef(err_union_ty)) {
5349 } else if (isByRef(err_union_ty, mod)) {
55625350 const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, "");
5563 if (isByRef(payload_ty)) {
5351 if (isByRef(payload_ty, mod)) {
55645352 if (can_elide_load)
55655353 return payload_ptr;
55665354
5567 return fg.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(target), false);
5355 return fg.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(mod), false);
55685356 }
55695357 const load_inst = fg.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, "");
5570 load_inst.setAlignment(payload_ty.abiAlignment(target));
5358 load_inst.setAlignment(payload_ty.abiAlignment(mod));
55715359 return load_inst;
55725360 }
55735361 return fg.builder.buildExtractValue(err_union, offset, "");
55745362 }
55755363
55765364 fn airSwitchBr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5365 const mod = self.dg.module;
55775366 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
55785367 const cond = try self.resolveInst(pl_op.operand);
55795368 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
55805369 const else_block = self.context.appendBasicBlock(self.llvm_func, "Else");
5581 const target = self.dg.module.getTarget();
5370 const target = mod.getTarget();
55825371 const llvm_usize = self.context.intType(target.ptrBitWidth());
55835372 const cond_int = if (cond.typeOf().getTypeKind() == .Pointer)
55845373 self.builder.buildPtrToInt(cond, llvm_usize, "")
......@@ -5623,6 +5412,7 @@ pub const FuncGen = struct {
56235412 }
56245413
56255414 fn airLoop(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5415 const mod = self.dg.module;
56265416 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
56275417 const loop = self.air.extraData(Air.Block, ty_pl.payload);
56285418 const body = self.air.extra[loop.end..][0..loop.data.body_len];
......@@ -5638,21 +5428,22 @@ pub const FuncGen = struct {
56385428 // would have been emitted already. Also the main loop in genBody can
56395429 // be while(true) instead of for(body), which will eliminate 1 branch on
56405430 // a hot path.
5641 if (body.len == 0 or !self.air.typeOfIndex(body[body.len - 1]).isNoReturn()) {
5431 if (body.len == 0 or !self.typeOfIndex(body[body.len - 1]).isNoReturn(mod)) {
56425432 _ = self.builder.buildBr(loop_block);
56435433 }
56445434 return null;
56455435 }
56465436
56475437 fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5438 const mod = self.dg.module;
56485439 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
5649 const operand_ty = self.air.typeOf(ty_op.operand);
5650 const array_ty = operand_ty.childType();
5440 const operand_ty = self.typeOf(ty_op.operand);
5441 const array_ty = operand_ty.childType(mod);
56515442 const llvm_usize = try self.dg.lowerType(Type.usize);
5652 const len = llvm_usize.constInt(array_ty.arrayLen(), .False);
5653 const slice_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
5443 const len = llvm_usize.constInt(array_ty.arrayLen(mod), .False);
5444 const slice_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst));
56545445 const operand = try self.resolveInst(ty_op.operand);
5655 if (!array_ty.hasRuntimeBitsIgnoreComptime()) {
5446 if (!array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
56565447 const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), operand, 0, "");
56575448 return self.builder.buildInsertValue(partial, len, 1, "");
56585449 }
......@@ -5666,30 +5457,31 @@ pub const FuncGen = struct {
56665457 }
56675458
56685459 fn airIntToFloat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5460 const mod = self.dg.module;
56695461 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
56705462
56715463 const operand = try self.resolveInst(ty_op.operand);
5672 const operand_ty = self.air.typeOf(ty_op.operand);
5673 const operand_scalar_ty = operand_ty.scalarType();
5464 const operand_ty = self.typeOf(ty_op.operand);
5465 const operand_scalar_ty = operand_ty.scalarType(mod);
56745466
5675 const dest_ty = self.air.typeOfIndex(inst);
5676 const dest_scalar_ty = dest_ty.scalarType();
5467 const dest_ty = self.typeOfIndex(inst);
5468 const dest_scalar_ty = dest_ty.scalarType(mod);
56775469 const dest_llvm_ty = try self.dg.lowerType(dest_ty);
5678 const target = self.dg.module.getTarget();
5470 const target = mod.getTarget();
56795471
56805472 if (intrinsicsAllowed(dest_scalar_ty, target)) {
5681 if (operand_scalar_ty.isSignedInt()) {
5473 if (operand_scalar_ty.isSignedInt(mod)) {
56825474 return self.builder.buildSIToFP(operand, dest_llvm_ty, "");
56835475 } else {
56845476 return self.builder.buildUIToFP(operand, dest_llvm_ty, "");
56855477 }
56865478 }
56875479
5688 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(target));
5480 const operand_bits = @intCast(u16, operand_scalar_ty.bitSize(mod));
56895481 const rt_int_bits = compilerRtIntBits(operand_bits);
56905482 const rt_int_ty = self.context.intType(rt_int_bits);
56915483 var extended = e: {
5692 if (operand_scalar_ty.isSignedInt()) {
5484 if (operand_scalar_ty.isSignedInt(mod)) {
56935485 break :e self.builder.buildSExtOrBitCast(operand, rt_int_ty, "");
56945486 } else {
56955487 break :e self.builder.buildZExtOrBitCast(operand, rt_int_ty, "");
......@@ -5698,7 +5490,7 @@ pub const FuncGen = struct {
56985490 const dest_bits = dest_scalar_ty.floatBits(target);
56995491 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
57005492 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);
5701 const sign_prefix = if (operand_scalar_ty.isSignedInt()) "" else "un";
5493 const sign_prefix = if (operand_scalar_ty.isSignedInt(mod)) "" else "un";
57025494 var fn_name_buf: [64]u8 = undefined;
57035495 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__float{s}{s}i{s}f", .{
57045496 sign_prefix,
......@@ -5724,27 +5516,28 @@ pub const FuncGen = struct {
57245516 fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
57255517 self.builder.setFastMath(want_fast_math);
57265518
5727 const target = self.dg.module.getTarget();
5519 const mod = self.dg.module;
5520 const target = mod.getTarget();
57285521 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
57295522
57305523 const operand = try self.resolveInst(ty_op.operand);
5731 const operand_ty = self.air.typeOf(ty_op.operand);
5732 const operand_scalar_ty = operand_ty.scalarType();
5524 const operand_ty = self.typeOf(ty_op.operand);
5525 const operand_scalar_ty = operand_ty.scalarType(mod);
57335526
5734 const dest_ty = self.air.typeOfIndex(inst);
5735 const dest_scalar_ty = dest_ty.scalarType();
5527 const dest_ty = self.typeOfIndex(inst);
5528 const dest_scalar_ty = dest_ty.scalarType(mod);
57365529 const dest_llvm_ty = try self.dg.lowerType(dest_ty);
57375530
57385531 if (intrinsicsAllowed(operand_scalar_ty, target)) {
57395532 // TODO set fast math flag
5740 if (dest_scalar_ty.isSignedInt()) {
5533 if (dest_scalar_ty.isSignedInt(mod)) {
57415534 return self.builder.buildFPToSI(operand, dest_llvm_ty, "");
57425535 } else {
57435536 return self.builder.buildFPToUI(operand, dest_llvm_ty, "");
57445537 }
57455538 }
57465539
5747 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(target)));
5540 const rt_int_bits = compilerRtIntBits(@intCast(u16, dest_scalar_ty.bitSize(mod)));
57485541 const ret_ty = self.context.intType(rt_int_bits);
57495542 const libc_ret_ty = if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) b: {
57505543 // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard
......@@ -5756,7 +5549,7 @@ pub const FuncGen = struct {
57565549 const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits);
57575550
57585551 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);
5759 const sign_prefix = if (dest_scalar_ty.isSignedInt()) "" else "uns";
5552 const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns";
57605553
57615554 var fn_name_buf: [64]u8 = undefined;
57625555 const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{
......@@ -5778,7 +5571,8 @@ pub const FuncGen = struct {
57785571 }
57795572
57805573 fn sliceOrArrayPtr(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value {
5781 if (ty.isSlice()) {
5574 const mod = fg.dg.module;
5575 if (ty.isSlice(mod)) {
57825576 return fg.builder.buildExtractValue(ptr, 0, "");
57835577 } else {
57845578 return ptr;
......@@ -5786,22 +5580,23 @@ pub const FuncGen = struct {
57865580 }
57875581
57885582 fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value {
5789 const target = fg.dg.module.getTarget();
5583 const mod = fg.dg.module;
5584 const target = mod.getTarget();
57905585 const llvm_usize_ty = fg.context.intType(target.ptrBitWidth());
5791 switch (ty.ptrSize()) {
5586 switch (ty.ptrSize(mod)) {
57925587 .Slice => {
57935588 const len = fg.builder.buildExtractValue(ptr, 1, "");
5794 const elem_ty = ty.childType();
5795 const abi_size = elem_ty.abiSize(target);
5589 const elem_ty = ty.childType(mod);
5590 const abi_size = elem_ty.abiSize(mod);
57965591 if (abi_size == 1) return len;
57975592 const abi_size_llvm_val = llvm_usize_ty.constInt(abi_size, .False);
57985593 return fg.builder.buildMul(len, abi_size_llvm_val, "");
57995594 },
58005595 .One => {
5801 const array_ty = ty.childType();
5802 const elem_ty = array_ty.childType();
5803 const abi_size = elem_ty.abiSize(target);
5804 return llvm_usize_ty.constInt(array_ty.arrayLen() * abi_size, .False);
5596 const array_ty = ty.childType(mod);
5597 const elem_ty = array_ty.childType(mod);
5598 const abi_size = elem_ty.abiSize(mod);
5599 return llvm_usize_ty.constInt(array_ty.arrayLen(mod) * abi_size, .False);
58055600 },
58065601 .Many, .C => unreachable,
58075602 }
......@@ -5814,67 +5609,69 @@ pub const FuncGen = struct {
58145609 }
58155610
58165611 fn airPtrSliceFieldPtr(self: *FuncGen, inst: Air.Inst.Index, index: c_uint) !?*llvm.Value {
5612 const mod = self.dg.module;
58175613 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
58185614 const slice_ptr = try self.resolveInst(ty_op.operand);
5819 const slice_ptr_ty = self.air.typeOf(ty_op.operand);
5820 const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType());
5615 const slice_ptr_ty = self.typeOf(ty_op.operand);
5616 const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType(mod));
58215617
58225618 return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, "");
58235619 }
58245620
58255621 fn airSliceElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5622 const mod = self.dg.module;
58265623 const inst = body_tail[0];
58275624 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5828 const slice_ty = self.air.typeOf(bin_op.lhs);
5625 const slice_ty = self.typeOf(bin_op.lhs);
58295626 const slice = try self.resolveInst(bin_op.lhs);
58305627 const index = try self.resolveInst(bin_op.rhs);
5831 const elem_ty = slice_ty.childType();
5628 const elem_ty = slice_ty.childType(mod);
58325629 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
58335630 const base_ptr = self.builder.buildExtractValue(slice, 0, "");
58345631 const indices: [1]*llvm.Value = .{index};
58355632 const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
5836 if (isByRef(elem_ty)) {
5633 if (isByRef(elem_ty, mod)) {
58375634 if (self.canElideLoad(body_tail))
58385635 return ptr;
58395636
5840 const target = self.dg.module.getTarget();
5841 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false);
5637 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(mod), false);
58425638 }
58435639
58445640 return self.load(ptr, slice_ty);
58455641 }
58465642
58475643 fn airSliceElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5644 const mod = self.dg.module;
58485645 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
58495646 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
5850 const slice_ty = self.air.typeOf(bin_op.lhs);
5647 const slice_ty = self.typeOf(bin_op.lhs);
58515648
58525649 const slice = try self.resolveInst(bin_op.lhs);
58535650 const index = try self.resolveInst(bin_op.rhs);
5854 const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType());
5651 const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType(mod));
58555652 const base_ptr = self.builder.buildExtractValue(slice, 0, "");
58565653 const indices: [1]*llvm.Value = .{index};
58575654 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
58585655 }
58595656
58605657 fn airArrayElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5658 const mod = self.dg.module;
58615659 const inst = body_tail[0];
58625660
58635661 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5864 const array_ty = self.air.typeOf(bin_op.lhs);
5662 const array_ty = self.typeOf(bin_op.lhs);
58655663 const array_llvm_val = try self.resolveInst(bin_op.lhs);
58665664 const rhs = try self.resolveInst(bin_op.rhs);
58675665 const array_llvm_ty = try self.dg.lowerType(array_ty);
5868 const elem_ty = array_ty.childType();
5869 if (isByRef(array_ty)) {
5666 const elem_ty = array_ty.childType(mod);
5667 if (isByRef(array_ty, mod)) {
58705668 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
5871 if (isByRef(elem_ty)) {
5669 if (isByRef(elem_ty, mod)) {
58725670 const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, "");
58735671 if (canElideLoad(self, body_tail))
58745672 return elem_ptr;
58755673
5876 const target = self.dg.module.getTarget();
5877 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(target), false);
5674 return self.loadByRef(elem_ptr, elem_ty, elem_ty.abiAlignment(mod), false);
58785675 } else {
58795676 const lhs_index = Air.refToIndex(bin_op.lhs).?;
58805677 const elem_llvm_ty = try self.dg.lowerType(elem_ty);
......@@ -5901,15 +5698,16 @@ pub const FuncGen = struct {
59015698 }
59025699
59035700 fn airPtrElemVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5701 const mod = self.dg.module;
59045702 const inst = body_tail[0];
59055703 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
5906 const ptr_ty = self.air.typeOf(bin_op.lhs);
5907 const elem_ty = ptr_ty.childType();
5704 const ptr_ty = self.typeOf(bin_op.lhs);
5705 const elem_ty = ptr_ty.childType(mod);
59085706 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
59095707 const base_ptr = try self.resolveInst(bin_op.lhs);
59105708 const rhs = try self.resolveInst(bin_op.rhs);
59115709 // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch
5912 const ptr = if (ptr_ty.isSinglePointer()) ptr: {
5710 const ptr = if (ptr_ty.isSinglePointer(mod)) ptr: {
59135711 // If this is a single-item pointer to an array, we need another index in the GEP.
59145712 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
59155713 break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
......@@ -5917,32 +5715,32 @@ pub const FuncGen = struct {
59175715 const indices: [1]*llvm.Value = .{rhs};
59185716 break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
59195717 };
5920 if (isByRef(elem_ty)) {
5718 if (isByRef(elem_ty, mod)) {
59215719 if (self.canElideLoad(body_tail))
59225720 return ptr;
59235721
5924 const target = self.dg.module.getTarget();
5925 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(target), false);
5722 return self.loadByRef(ptr, elem_ty, elem_ty.abiAlignment(mod), false);
59265723 }
59275724
59285725 return self.load(ptr, ptr_ty);
59295726 }
59305727
59315728 fn airPtrElemPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5729 const mod = self.dg.module;
59325730 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
59335731 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
5934 const ptr_ty = self.air.typeOf(bin_op.lhs);
5935 const elem_ty = ptr_ty.childType();
5936 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);
5732 const ptr_ty = self.typeOf(bin_op.lhs);
5733 const elem_ty = ptr_ty.childType(mod);
5734 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty);
59375735
59385736 const base_ptr = try self.resolveInst(bin_op.lhs);
59395737 const rhs = try self.resolveInst(bin_op.rhs);
59405738
59415739 const elem_ptr = self.air.getRefType(ty_pl.ty);
5942 if (elem_ptr.ptrInfo().data.vector_index != .none) return base_ptr;
5740 if (elem_ptr.ptrInfo(mod).vector_index != .none) return base_ptr;
59435741
59445742 const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty);
5945 if (ptr_ty.isSinglePointer()) {
5743 if (ptr_ty.isSinglePointer(mod)) {
59465744 // If this is a single-item pointer to an array, we need another index in the GEP.
59475745 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), rhs };
59485746 return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, "");
......@@ -5956,7 +5754,7 @@ pub const FuncGen = struct {
59565754 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
59575755 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
59585756 const struct_ptr = try self.resolveInst(struct_field.struct_operand);
5959 const struct_ptr_ty = self.air.typeOf(struct_field.struct_operand);
5757 const struct_ptr_ty = self.typeOf(struct_field.struct_operand);
59605758 return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, struct_field.field_index);
59615759 }
59625760
......@@ -5967,41 +5765,41 @@ pub const FuncGen = struct {
59675765 ) !?*llvm.Value {
59685766 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
59695767 const struct_ptr = try self.resolveInst(ty_op.operand);
5970 const struct_ptr_ty = self.air.typeOf(ty_op.operand);
5768 const struct_ptr_ty = self.typeOf(ty_op.operand);
59715769 return self.fieldPtr(inst, struct_ptr, struct_ptr_ty, field_index);
59725770 }
59735771
59745772 fn airStructFieldVal(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
5773 const mod = self.dg.module;
59755774 const inst = body_tail[0];
59765775 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
59775776 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
5978 const struct_ty = self.air.typeOf(struct_field.struct_operand);
5777 const struct_ty = self.typeOf(struct_field.struct_operand);
59795778 const struct_llvm_val = try self.resolveInst(struct_field.struct_operand);
59805779 const field_index = struct_field.field_index;
5981 const field_ty = struct_ty.structFieldType(field_index);
5982 if (!field_ty.hasRuntimeBitsIgnoreComptime()) {
5780 const field_ty = struct_ty.structFieldType(field_index, mod);
5781 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) {
59835782 return null;
59845783 }
5985 const target = self.dg.module.getTarget();
59865784
5987 if (!isByRef(struct_ty)) {
5988 assert(!isByRef(field_ty));
5989 switch (struct_ty.zigTypeTag()) {
5990 .Struct => switch (struct_ty.containerLayout()) {
5785 if (!isByRef(struct_ty, mod)) {
5786 assert(!isByRef(field_ty, mod));
5787 switch (struct_ty.zigTypeTag(mod)) {
5788 .Struct => switch (struct_ty.containerLayout(mod)) {
59915789 .Packed => {
5992 const struct_obj = struct_ty.castTag(.@"struct").?.data;
5993 const bit_offset = struct_obj.packedFieldBitOffset(target, field_index);
5790 const struct_obj = mod.typeToStruct(struct_ty).?;
5791 const bit_offset = struct_obj.packedFieldBitOffset(mod, field_index);
59945792 const containing_int = struct_llvm_val;
59955793 const shift_amt = containing_int.typeOf().constInt(bit_offset, .False);
59965794 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
59975795 const elem_llvm_ty = try self.dg.lowerType(field_ty);
5998 if (field_ty.zigTypeTag() == .Float or field_ty.zigTypeTag() == .Vector) {
5999 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
5796 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
5797 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
60005798 const same_size_int = self.context.intType(elem_bits);
60015799 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
60025800 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
6003 } else if (field_ty.isPtrAtRuntime()) {
6004 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
5801 } else if (field_ty.isPtrAtRuntime(mod)) {
5802 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
60055803 const same_size_int = self.context.intType(elem_bits);
60065804 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
60075805 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
......@@ -6009,22 +5807,21 @@ pub const FuncGen = struct {
60095807 return self.builder.buildTrunc(shifted_value, elem_llvm_ty, "");
60105808 },
60115809 else => {
6012 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6013 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
5810 const llvm_field_index = llvmField(struct_ty, field_index, mod).?.index;
60145811 return self.builder.buildExtractValue(struct_llvm_val, llvm_field_index, "");
60155812 },
60165813 },
60175814 .Union => {
6018 assert(struct_ty.containerLayout() == .Packed);
5815 assert(struct_ty.containerLayout(mod) == .Packed);
60195816 const containing_int = struct_llvm_val;
60205817 const elem_llvm_ty = try self.dg.lowerType(field_ty);
6021 if (field_ty.zigTypeTag() == .Float or field_ty.zigTypeTag() == .Vector) {
6022 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
5818 if (field_ty.zigTypeTag(mod) == .Float or field_ty.zigTypeTag(mod) == .Vector) {
5819 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
60235820 const same_size_int = self.context.intType(elem_bits);
60245821 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");
60255822 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
6026 } else if (field_ty.isPtrAtRuntime()) {
6027 const elem_bits = @intCast(c_uint, field_ty.bitSize(target));
5823 } else if (field_ty.isPtrAtRuntime(mod)) {
5824 const elem_bits = @intCast(c_uint, field_ty.bitSize(mod));
60285825 const same_size_int = self.context.intType(elem_bits);
60295826 const truncated_int = self.builder.buildTrunc(containing_int, same_size_int, "");
60305827 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
......@@ -6035,30 +5832,35 @@ pub const FuncGen = struct {
60355832 }
60365833 }
60375834
6038 switch (struct_ty.zigTypeTag()) {
5835 switch (struct_ty.zigTypeTag(mod)) {
60395836 .Struct => {
6040 assert(struct_ty.containerLayout() != .Packed);
6041 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6042 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
5837 assert(struct_ty.containerLayout(mod) != .Packed);
5838 const llvm_field = llvmField(struct_ty, field_index, mod).?;
60435839 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6044 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, "");
6045 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
6046 if (isByRef(field_ty)) {
5840 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field.index, "");
5841 const field_ptr_ty = try mod.ptrType(.{
5842 .child = llvm_field.ty.toIntern(),
5843 .flags = .{
5844 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
5845 },
5846 });
5847 if (isByRef(field_ty, mod)) {
60475848 if (canElideLoad(self, body_tail))
60485849 return field_ptr;
60495850
6050 return self.loadByRef(field_ptr, field_ty, ptr_ty_buf.data.alignment(target), false);
5851 assert(llvm_field.alignment != 0);
5852 return self.loadByRef(field_ptr, field_ty, llvm_field.alignment, false);
60515853 } else {
60525854 return self.load(field_ptr, field_ptr_ty);
60535855 }
60545856 },
60555857 .Union => {
60565858 const union_llvm_ty = try self.dg.lowerType(struct_ty);
6057 const layout = struct_ty.unionGetLayout(target);
5859 const layout = struct_ty.unionGetLayout(mod);
60585860 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
60595861 const field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, "");
60605862 const llvm_field_ty = try self.dg.lowerType(field_ty);
6061 if (isByRef(field_ty)) {
5863 if (isByRef(field_ty, mod)) {
60625864 if (canElideLoad(self, body_tail))
60635865 return field_ptr;
60645866
......@@ -6072,14 +5874,15 @@ pub const FuncGen = struct {
60725874 }
60735875
60745876 fn airFieldParentPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
5877 const mod = self.dg.module;
60755878 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
60765879 const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data;
60775880
60785881 const field_ptr = try self.resolveInst(extra.field_ptr);
60795882
60805883 const target = self.dg.module.getTarget();
6081 const parent_ty = self.air.getRefType(ty_pl.ty).childType();
6082 const field_offset = parent_ty.structFieldOffset(extra.field_index, target);
5884 const parent_ty = self.air.getRefType(ty_pl.ty).childType(mod);
5885 const field_offset = parent_ty.structFieldOffset(extra.field_index, mod);
60835886
60845887 const res_ty = try self.dg.lowerType(self.air.getRefType(ty_pl.ty));
60855888 if (field_offset == 0) {
......@@ -6120,12 +5923,13 @@ pub const FuncGen = struct {
61205923
61215924 fn airDbgInlineBegin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
61225925 const dib = self.dg.object.di_builder orelse return null;
6123 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5926 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
61245927
6125 const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
5928 const mod = self.dg.module;
5929 const func = mod.funcPtr(ty_fn.func);
61265930 const decl_index = func.owner_decl;
6127 const decl = self.dg.module.declPtr(decl_index);
6128 const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);
5931 const decl = mod.declPtr(decl_index);
5932 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
61295933 self.di_file = di_file;
61305934 const line_number = decl.src_line + 1;
61315935 const cur_debug_location = self.builder.getCurrentDebugLocation2();
......@@ -6136,22 +5940,37 @@ pub const FuncGen = struct {
61365940 .base_line = self.base_line,
61375941 });
61385942
6139 const fqn = try decl.getFullyQualifiedName(self.dg.module);
6140 defer self.gpa.free(fqn);
6141
6142 const is_internal_linkage = !self.dg.module.decl_exports.contains(decl_index);
5943 const fqn = try decl.getFullyQualifiedName(mod);
5944
5945 const is_internal_linkage = !mod.decl_exports.contains(decl_index);
5946 const fn_ty = try mod.funcType(.{
5947 .param_types = &.{},
5948 .return_type = .void_type,
5949 .alignment = .none,
5950 .noalias_bits = 0,
5951 .comptime_bits = 0,
5952 .cc = .Unspecified,
5953 .is_var_args = false,
5954 .is_generic = false,
5955 .is_noinline = false,
5956 .align_is_generic = false,
5957 .cc_is_generic = false,
5958 .section_is_generic = false,
5959 .addrspace_is_generic = false,
5960 });
5961 const fn_di_ty = try self.dg.object.lowerDebugType(fn_ty, .full);
61435962 const subprogram = dib.createFunction(
61445963 di_file.toScope(),
6145 decl.name,
6146 fqn,
5964 mod.intern_pool.stringToSlice(decl.name),
5965 mod.intern_pool.stringToSlice(fqn),
61475966 di_file,
61485967 line_number,
6149 try self.dg.object.lowerDebugType(Type.initTag(.fn_void_no_args), .full),
5968 fn_di_ty,
61505969 is_internal_linkage,
61515970 true, // is definition
61525971 line_number + func.lbrace_line, // scope line
61535972 llvm.DIFlags.StaticMember,
6154 self.dg.module.comp.bin_file.options.optimize_mode != .Debug,
5973 mod.comp.bin_file.options.optimize_mode != .Debug,
61555974 null, // decl_subprogram
61565975 );
61575976
......@@ -6163,12 +5982,12 @@ pub const FuncGen = struct {
61635982
61645983 fn airDbgInlineEnd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
61655984 if (self.dg.object.di_builder == null) return null;
6166 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
5985 const ty_fn = self.air.instructions.items(.data)[inst].ty_fn;
61675986
6168 const func = self.air.values[ty_pl.payload].castTag(.function).?.data;
61695987 const mod = self.dg.module;
5988 const func = mod.funcPtr(ty_fn.func);
61705989 const decl = mod.declPtr(func.owner_decl);
6171 const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);
5990 const di_file = try self.dg.object.getDIFile(self.gpa, mod.namespacePtr(decl.src_namespace).file_scope);
61725991 self.di_file = di_file;
61735992 const old = self.dbg_inlined.pop();
61745993 self.di_scope = old.scope;
......@@ -6192,18 +6011,19 @@ pub const FuncGen = struct {
61926011 }
61936012
61946013 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6014 const mod = self.dg.module;
61956015 const dib = self.dg.object.di_builder orelse return null;
61966016 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
61976017 const operand = try self.resolveInst(pl_op.operand);
61986018 const name = self.air.nullTerminatedString(pl_op.payload);
6199 const ptr_ty = self.air.typeOf(pl_op.operand);
6019 const ptr_ty = self.typeOf(pl_op.operand);
62006020
62016021 const di_local_var = dib.createAutoVariable(
62026022 self.di_scope.?,
62036023 name.ptr,
62046024 self.di_file.?,
62056025 self.prev_dbg_line,
6206 try self.dg.object.lowerDebugType(ptr_ty.childType(), .full),
6026 try self.dg.object.lowerDebugType(ptr_ty.childType(mod), .full),
62076027 true, // always preserve
62086028 0, // flags
62096029 );
......@@ -6221,7 +6041,7 @@ pub const FuncGen = struct {
62216041 const dib = self.dg.object.di_builder orelse return null;
62226042 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
62236043 const operand = try self.resolveInst(pl_op.operand);
6224 const operand_ty = self.air.typeOf(pl_op.operand);
6044 const operand_ty = self.typeOf(pl_op.operand);
62256045 const name = self.air.nullTerminatedString(pl_op.payload);
62266046
62276047 if (needDbgVarWorkaround(self.dg)) {
......@@ -6243,10 +6063,11 @@ pub const FuncGen = struct {
62436063 null;
62446064 const debug_loc = llvm.getDebugLoc(self.prev_dbg_line, self.prev_dbg_column, self.di_scope.?, inlined_at);
62456065 const insert_block = self.builder.getInsertBlock();
6246 if (isByRef(operand_ty)) {
6066 const mod = self.dg.module;
6067 if (isByRef(operand_ty, mod)) {
62476068 _ = dib.insertDeclareAtEnd(operand, di_local_var, debug_loc, insert_block);
62486069 } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) {
6249 const alignment = operand_ty.abiAlignment(self.dg.module.getTarget());
6070 const alignment = operand_ty.abiAlignment(mod);
62506071 const alloca = self.buildAlloca(operand.typeOf(), alignment);
62516072 const store_inst = self.builder.buildStore(operand, alloca);
62526073 store_inst.setAlignment(alignment);
......@@ -6294,7 +6115,8 @@ pub const FuncGen = struct {
62946115 // This stores whether we need to add an elementtype attribute and
62956116 // if so, the element type itself.
62966117 const llvm_param_attrs = try arena.alloc(?*llvm.Type, max_param_count);
6297 const target = self.dg.module.getTarget();
6118 const mod = self.dg.module;
6119 const target = mod.getTarget();
62986120
62996121 var llvm_ret_i: usize = 0;
63006122 var llvm_param_i: usize = 0;
......@@ -6321,9 +6143,9 @@ pub const FuncGen = struct {
63216143 llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint);
63226144 if (output != .none) {
63236145 const output_inst = try self.resolveInst(output);
6324 const output_ty = self.air.typeOf(output);
6325 assert(output_ty.zigTypeTag() == .Pointer);
6326 const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType());
6146 const output_ty = self.typeOf(output);
6147 assert(output_ty.zigTypeTag(mod) == .Pointer);
6148 const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType(mod));
63276149
63286150 if (llvm_ret_indirect[i]) {
63296151 // Pass the result by reference as an indirect output (e.g. "=*m")
......@@ -6339,7 +6161,7 @@ pub const FuncGen = struct {
63396161 llvm_ret_i += 1;
63406162 }
63416163 } else {
6342 const ret_ty = self.air.typeOfIndex(inst);
6164 const ret_ty = self.typeOfIndex(inst);
63436165 llvm_ret_types[llvm_ret_i] = try self.dg.lowerType(ret_ty);
63446166 llvm_ret_i += 1;
63456167 }
......@@ -6374,15 +6196,15 @@ pub const FuncGen = struct {
63746196 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
63756197
63766198 const arg_llvm_value = try self.resolveInst(input);
6377 const arg_ty = self.air.typeOf(input);
6199 const arg_ty = self.typeOf(input);
63786200 var llvm_elem_ty: ?*llvm.Type = null;
6379 if (isByRef(arg_ty)) {
6201 if (isByRef(arg_ty, mod)) {
63806202 llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty);
63816203 if (constraintAllowsMemory(constraint)) {
63826204 llvm_param_values[llvm_param_i] = arg_llvm_value;
63836205 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
63846206 } else {
6385 const alignment = arg_ty.abiAlignment(target);
6207 const alignment = arg_ty.abiAlignment(mod);
63866208 const arg_llvm_ty = try self.dg.lowerType(arg_ty);
63876209 const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, "");
63886210 load_inst.setAlignment(alignment);
......@@ -6394,7 +6216,7 @@ pub const FuncGen = struct {
63946216 llvm_param_values[llvm_param_i] = arg_llvm_value;
63956217 llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf();
63966218 } else {
6397 const alignment = arg_ty.abiAlignment(target);
6219 const alignment = arg_ty.abiAlignment(mod);
63986220 const arg_ptr = self.buildAlloca(arg_llvm_value.typeOf(), alignment);
63996221 const store_inst = self.builder.buildStore(arg_llvm_value, arg_ptr);
64006222 store_inst.setAlignment(alignment);
......@@ -6424,7 +6246,7 @@ pub const FuncGen = struct {
64246246 // an elementtype(<ty>) attribute.
64256247 if (constraint[0] == '*') {
64266248 llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse
6427 try self.dg.lowerPtrElemTy(arg_ty.childType());
6249 try self.dg.lowerPtrElemTy(arg_ty.childType(mod));
64286250 } else {
64296251 llvm_param_attrs[llvm_param_i] = null;
64306252 }
......@@ -6596,10 +6418,10 @@ pub const FuncGen = struct {
65966418
65976419 if (output != .none) {
65986420 const output_ptr = try self.resolveInst(output);
6599 const output_ptr_ty = self.air.typeOf(output);
6421 const output_ptr_ty = self.typeOf(output);
66006422
66016423 const store_inst = self.builder.buildStore(output_value, output_ptr);
6602 store_inst.setAlignment(output_ptr_ty.ptrAlignment(target));
6424 store_inst.setAlignment(output_ptr_ty.ptrAlignment(mod));
66036425 } else {
66046426 ret_val = output_value;
66056427 }
......@@ -6615,22 +6437,21 @@ pub const FuncGen = struct {
66156437 operand_is_ptr: bool,
66166438 pred: llvm.IntPredicate,
66176439 ) !?*llvm.Value {
6440 const mod = self.dg.module;
66186441 const un_op = self.air.instructions.items(.data)[inst].un_op;
66196442 const operand = try self.resolveInst(un_op);
6620 const operand_ty = self.air.typeOf(un_op);
6621 const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
6443 const operand_ty = self.typeOf(un_op);
6444 const optional_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
66226445 const optional_llvm_ty = try self.dg.lowerType(optional_ty);
6623 var buf: Type.Payload.ElemType = undefined;
6624 const payload_ty = optional_ty.optionalChild(&buf);
6625 if (optional_ty.optionalReprIsPayload()) {
6446 const payload_ty = optional_ty.optionalChild(mod);
6447 if (optional_ty.optionalReprIsPayload(mod)) {
66266448 const loaded = if (operand_is_ptr)
66276449 self.builder.buildLoad(optional_llvm_ty, operand, "")
66286450 else
66296451 operand;
6630 if (payload_ty.isSlice()) {
6452 if (payload_ty.isSlice(mod)) {
66316453 const slice_ptr = self.builder.buildExtractValue(loaded, 0, "");
6632 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
6633 const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf));
6454 const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(mod));
66346455 return self.builder.buildICmp(pred, slice_ptr, ptr_ty.constNull(), "");
66356456 }
66366457 return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), "");
......@@ -6638,7 +6459,7 @@ pub const FuncGen = struct {
66386459
66396460 comptime assert(optional_layout_version == 3);
66406461
6641 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6462 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
66426463 const loaded = if (operand_is_ptr)
66436464 self.builder.buildLoad(optional_llvm_ty, operand, "")
66446465 else
......@@ -6647,7 +6468,7 @@ pub const FuncGen = struct {
66476468 return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), "");
66486469 }
66496470
6650 const is_by_ref = operand_is_ptr or isByRef(optional_ty);
6471 const is_by_ref = operand_is_ptr or isByRef(optional_ty, mod);
66516472 const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref);
66526473 if (pred == .EQ) {
66536474 return self.builder.buildNot(non_null_bit, "");
......@@ -6662,15 +6483,16 @@ pub const FuncGen = struct {
66626483 op: llvm.IntPredicate,
66636484 operand_is_ptr: bool,
66646485 ) !?*llvm.Value {
6486 const mod = self.dg.module;
66656487 const un_op = self.air.instructions.items(.data)[inst].un_op;
66666488 const operand = try self.resolveInst(un_op);
6667 const operand_ty = self.air.typeOf(un_op);
6668 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
6669 const payload_ty = err_union_ty.errorUnionPayload();
6489 const operand_ty = self.typeOf(un_op);
6490 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6491 const payload_ty = err_union_ty.errorUnionPayload(mod);
66706492 const err_set_ty = try self.dg.lowerType(Type.anyerror);
66716493 const zero = err_set_ty.constNull();
66726494
6673 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
6495 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
66746496 const llvm_i1 = self.context.intType(1);
66756497 switch (op) {
66766498 .EQ => return llvm_i1.constInt(1, .False), // 0 == 0
......@@ -6679,7 +6501,7 @@ pub const FuncGen = struct {
66796501 }
66806502 }
66816503
6682 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6504 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
66836505 const loaded = if (operand_is_ptr)
66846506 self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "")
66856507 else
......@@ -6687,10 +6509,9 @@ pub const FuncGen = struct {
66876509 return self.builder.buildICmp(op, loaded, zero, "");
66886510 }
66896511
6690 const target = self.dg.module.getTarget();
6691 const err_field_index = errUnionErrorOffset(payload_ty, target);
6512 const err_field_index = errUnionErrorOffset(payload_ty, mod);
66926513
6693 if (operand_is_ptr or isByRef(err_union_ty)) {
6514 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
66946515 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
66956516 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, "");
66966517 const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, "");
......@@ -6702,17 +6523,17 @@ pub const FuncGen = struct {
67026523 }
67036524
67046525 fn airOptionalPayloadPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6526 const mod = self.dg.module;
67056527 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
67066528 const operand = try self.resolveInst(ty_op.operand);
6707 const optional_ty = self.air.typeOf(ty_op.operand).childType();
6708 var buf: Type.Payload.ElemType = undefined;
6709 const payload_ty = optional_ty.optionalChild(&buf);
6710 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6529 const optional_ty = self.typeOf(ty_op.operand).childType(mod);
6530 const payload_ty = optional_ty.optionalChild(mod);
6531 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
67116532 // We have a pointer to a zero-bit value and we need to return
67126533 // a pointer to a zero-bit value.
67136534 return operand;
67146535 }
6715 if (optional_ty.optionalReprIsPayload()) {
6536 if (optional_ty.optionalReprIsPayload(mod)) {
67166537 // The payload and the optional are the same value.
67176538 return operand;
67186539 }
......@@ -6723,18 +6544,18 @@ pub const FuncGen = struct {
67236544 fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
67246545 comptime assert(optional_layout_version == 3);
67256546
6547 const mod = self.dg.module;
67266548 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
67276549 const operand = try self.resolveInst(ty_op.operand);
6728 const optional_ty = self.air.typeOf(ty_op.operand).childType();
6729 var buf: Type.Payload.ElemType = undefined;
6730 const payload_ty = optional_ty.optionalChild(&buf);
6550 const optional_ty = self.typeOf(ty_op.operand).childType(mod);
6551 const payload_ty = optional_ty.optionalChild(mod);
67316552 const non_null_bit = self.context.intType(8).constInt(1, .False);
6732 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6553 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
67336554 // We have a pointer to a i8. We need to set it to 1 and then return the same pointer.
67346555 _ = self.builder.buildStore(non_null_bit, operand);
67356556 return operand;
67366557 }
6737 if (optional_ty.optionalReprIsPayload()) {
6558 if (optional_ty.optionalReprIsPayload(mod)) {
67386559 // The payload and the optional are the same value.
67396560 // Setting to non-null will be done when the payload is set.
67406561 return operand;
......@@ -6754,20 +6575,21 @@ pub const FuncGen = struct {
67546575 }
67556576
67566577 fn airOptionalPayload(self: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
6578 const mod = self.dg.module;
67576579 const inst = body_tail[0];
67586580 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
67596581 const operand = try self.resolveInst(ty_op.operand);
6760 const optional_ty = self.air.typeOf(ty_op.operand);
6761 const payload_ty = self.air.typeOfIndex(inst);
6762 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null;
6582 const optional_ty = self.typeOf(ty_op.operand);
6583 const payload_ty = self.typeOfIndex(inst);
6584 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
67636585
6764 if (optional_ty.optionalReprIsPayload()) {
6586 if (optional_ty.optionalReprIsPayload(mod)) {
67656587 // Payload value is the same as the optional value.
67666588 return operand;
67676589 }
67686590
67696591 const opt_llvm_ty = try self.dg.lowerType(optional_ty);
6770 const can_elide_load = if (isByRef(payload_ty)) self.canElideLoad(body_tail) else false;
6592 const can_elide_load = if (isByRef(payload_ty, mod)) self.canElideLoad(body_tail) else false;
67716593 return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty, can_elide_load);
67726594 }
67736595
......@@ -6776,32 +6598,32 @@ pub const FuncGen = struct {
67766598 body_tail: []const Air.Inst.Index,
67776599 operand_is_ptr: bool,
67786600 ) !?*llvm.Value {
6601 const mod = self.dg.module;
67796602 const inst = body_tail[0];
67806603 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
67816604 const operand = try self.resolveInst(ty_op.operand);
6782 const operand_ty = self.air.typeOf(ty_op.operand);
6783 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
6784 const result_ty = self.air.typeOfIndex(inst);
6785 const payload_ty = if (operand_is_ptr) result_ty.childType() else result_ty;
6786 const target = self.dg.module.getTarget();
6605 const operand_ty = self.typeOf(ty_op.operand);
6606 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6607 const result_ty = self.typeOfIndex(inst);
6608 const payload_ty = if (operand_is_ptr) result_ty.childType(mod) else result_ty;
67876609
6788 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6610 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
67896611 return if (operand_is_ptr) operand else null;
67906612 }
6791 const offset = errUnionPayloadOffset(payload_ty, target);
6613 const offset = errUnionPayloadOffset(payload_ty, mod);
67926614 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
67936615 if (operand_is_ptr) {
67946616 return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
6795 } else if (isByRef(err_union_ty)) {
6617 } else if (isByRef(err_union_ty, mod)) {
67966618 const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
6797 if (isByRef(payload_ty)) {
6619 if (isByRef(payload_ty, mod)) {
67986620 if (self.canElideLoad(body_tail))
67996621 return payload_ptr;
68006622
6801 return self.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(target), false);
6623 return self.loadByRef(payload_ptr, payload_ty, payload_ty.abiAlignment(mod), false);
68026624 }
68036625 const load_inst = self.builder.buildLoad(err_union_llvm_ty.structGetTypeAtIndex(offset), payload_ptr, "");
6804 load_inst.setAlignment(payload_ty.abiAlignment(target));
6626 load_inst.setAlignment(payload_ty.abiAlignment(mod));
68056627 return load_inst;
68066628 }
68076629 return self.builder.buildExtractValue(operand, offset, "");
......@@ -6812,11 +6634,12 @@ pub const FuncGen = struct {
68126634 inst: Air.Inst.Index,
68136635 operand_is_ptr: bool,
68146636 ) !?*llvm.Value {
6637 const mod = self.dg.module;
68156638 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
68166639 const operand = try self.resolveInst(ty_op.operand);
6817 const operand_ty = self.air.typeOf(ty_op.operand);
6818 const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty;
6819 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
6640 const operand_ty = self.typeOf(ty_op.operand);
6641 const err_union_ty = if (operand_is_ptr) operand_ty.childType(mod) else operand_ty;
6642 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
68206643 const err_llvm_ty = try self.dg.lowerType(Type.anyerror);
68216644 if (operand_is_ptr) {
68226645 return operand;
......@@ -6827,16 +6650,15 @@ pub const FuncGen = struct {
68276650
68286651 const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror);
68296652
6830 const payload_ty = err_union_ty.errorUnionPayload();
6831 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6653 const payload_ty = err_union_ty.errorUnionPayload(mod);
6654 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
68326655 if (!operand_is_ptr) return operand;
68336656 return self.builder.buildLoad(err_set_llvm_ty, operand, "");
68346657 }
68356658
6836 const target = self.dg.module.getTarget();
6837 const offset = errUnionErrorOffset(payload_ty, target);
6659 const offset = errUnionErrorOffset(payload_ty, mod);
68386660
6839 if (operand_is_ptr or isByRef(err_union_ty)) {
6661 if (operand_is_ptr or isByRef(err_union_ty, mod)) {
68406662 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
68416663 const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, "");
68426664 return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, "");
......@@ -6846,30 +6668,30 @@ pub const FuncGen = struct {
68466668 }
68476669
68486670 fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6671 const mod = self.dg.module;
68496672 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
68506673 const operand = try self.resolveInst(ty_op.operand);
6851 const err_union_ty = self.air.typeOf(ty_op.operand).childType();
6674 const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
68526675
6853 const payload_ty = err_union_ty.errorUnionPayload();
6854 const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero });
6855 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6676 const payload_ty = err_union_ty.errorUnionPayload(mod);
6677 const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = try mod.intValue(Type.err_int, 0) });
6678 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
68566679 _ = self.builder.buildStore(non_error_val, operand);
68576680 return operand;
68586681 }
6859 const target = self.dg.module.getTarget();
68606682 const err_union_llvm_ty = try self.dg.lowerType(err_union_ty);
68616683 {
6862 const error_offset = errUnionErrorOffset(payload_ty, target);
6684 const error_offset = errUnionErrorOffset(payload_ty, mod);
68636685 // First set the non-error value.
68646686 const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, "");
68656687 const store_inst = self.builder.buildStore(non_error_val, non_null_ptr);
6866 store_inst.setAlignment(Type.anyerror.abiAlignment(target));
6688 store_inst.setAlignment(Type.anyerror.abiAlignment(mod));
68676689 }
68686690 // Then return the payload pointer (only if it is used).
68696691 if (self.liveness.isUnused(inst))
68706692 return null;
68716693
6872 const payload_offset = errUnionPayloadOffset(payload_ty, target);
6694 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
68736695 return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, "");
68746696 }
68756697
......@@ -6885,42 +6707,41 @@ pub const FuncGen = struct {
68856707 }
68866708
68876709 fn airSaveErrReturnTraceIndex(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6888 const target = self.dg.module.getTarget();
6889
68906710 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
68916711 //const struct_ty = try self.resolveInst(ty_pl.ty);
68926712 const struct_ty = self.air.getRefType(ty_pl.ty);
68936713 const field_index = ty_pl.payload;
68946714
6895 var ptr_ty_buf: Type.Payload.Pointer = undefined;
6896 const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?;
6715 const mod = self.dg.module;
6716 const llvm_field = llvmField(struct_ty, field_index, mod).?;
68976717 const struct_llvm_ty = try self.dg.lowerType(struct_ty);
6898 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field_index, "");
6899 const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base);
6718 const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, self.err_ret_trace.?, llvm_field.index, "");
6719 const field_ptr_ty = try mod.ptrType(.{
6720 .child = llvm_field.ty.toIntern(),
6721 .flags = .{
6722 .alignment = InternPool.Alignment.fromNonzeroByteUnits(llvm_field.alignment),
6723 },
6724 });
69006725 return self.load(field_ptr, field_ptr_ty);
69016726 }
69026727
69036728 fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6729 const mod = self.dg.module;
69046730 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6905 const payload_ty = self.air.typeOf(ty_op.operand);
6731 const payload_ty = self.typeOf(ty_op.operand);
69066732 const non_null_bit = self.context.intType(8).constInt(1, .False);
69076733 comptime assert(optional_layout_version == 3);
6908 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return non_null_bit;
6734 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return non_null_bit;
69096735 const operand = try self.resolveInst(ty_op.operand);
6910 const optional_ty = self.air.typeOfIndex(inst);
6911 if (optional_ty.optionalReprIsPayload()) {
6736 const optional_ty = self.typeOfIndex(inst);
6737 if (optional_ty.optionalReprIsPayload(mod)) {
69126738 return operand;
69136739 }
69146740 const llvm_optional_ty = try self.dg.lowerType(optional_ty);
6915 if (isByRef(optional_ty)) {
6916 const target = self.dg.module.getTarget();
6917 const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(target));
6741 if (isByRef(optional_ty, mod)) {
6742 const optional_ptr = self.buildAlloca(llvm_optional_ty, optional_ty.abiAlignment(mod));
69186743 const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, "");
6919 var ptr_ty_payload: Type.Payload.ElemType = .{
6920 .base = .{ .tag = .single_mut_pointer },
6921 .data = payload_ty,
6922 };
6923 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
6744 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
69246745 try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
69256746 const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, "");
69266747 _ = self.builder.buildStore(non_null_bit, non_null_ptr);
......@@ -6931,30 +6752,26 @@ pub const FuncGen = struct {
69316752 }
69326753
69336754 fn airWrapErrUnionPayload(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6755 const mod = self.dg.module;
69346756 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6935 const err_un_ty = self.air.typeOfIndex(inst);
6757 const err_un_ty = self.typeOfIndex(inst);
69366758 const operand = try self.resolveInst(ty_op.operand);
6937 const payload_ty = self.air.typeOf(ty_op.operand);
6938 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6759 const payload_ty = self.typeOf(ty_op.operand);
6760 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
69396761 return operand;
69406762 }
69416763 const ok_err_code = (try self.dg.lowerType(Type.anyerror)).constNull();
69426764 const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);
69436765
6944 const target = self.dg.module.getTarget();
6945 const payload_offset = errUnionPayloadOffset(payload_ty, target);
6946 const error_offset = errUnionErrorOffset(payload_ty, target);
6947 if (isByRef(err_un_ty)) {
6948 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target));
6766 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
6767 const error_offset = errUnionErrorOffset(payload_ty, mod);
6768 if (isByRef(err_un_ty, mod)) {
6769 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod));
69496770 const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, "");
69506771 const store_inst = self.builder.buildStore(ok_err_code, err_ptr);
6951 store_inst.setAlignment(Type.anyerror.abiAlignment(target));
6772 store_inst.setAlignment(Type.anyerror.abiAlignment(mod));
69526773 const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, "");
6953 var ptr_ty_payload: Type.Payload.ElemType = .{
6954 .base = .{ .tag = .single_mut_pointer },
6955 .data = payload_ty,
6956 };
6957 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
6774 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
69586775 try self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic);
69596776 return result_ptr;
69606777 }
......@@ -6964,29 +6781,25 @@ pub const FuncGen = struct {
69646781 }
69656782
69666783 fn airWrapErrUnionErr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6784 const mod = self.dg.module;
69676785 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
6968 const err_un_ty = self.air.typeOfIndex(inst);
6969 const payload_ty = err_un_ty.errorUnionPayload();
6786 const err_un_ty = self.typeOfIndex(inst);
6787 const payload_ty = err_un_ty.errorUnionPayload(mod);
69706788 const operand = try self.resolveInst(ty_op.operand);
6971 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
6789 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
69726790 return operand;
69736791 }
69746792 const err_un_llvm_ty = try self.dg.lowerType(err_un_ty);
69756793
6976 const target = self.dg.module.getTarget();
6977 const payload_offset = errUnionPayloadOffset(payload_ty, target);
6978 const error_offset = errUnionErrorOffset(payload_ty, target);
6979 if (isByRef(err_un_ty)) {
6980 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(target));
6794 const payload_offset = errUnionPayloadOffset(payload_ty, mod);
6795 const error_offset = errUnionErrorOffset(payload_ty, mod);
6796 if (isByRef(err_un_ty, mod)) {
6797 const result_ptr = self.buildAlloca(err_un_llvm_ty, err_un_ty.abiAlignment(mod));
69816798 const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, "");
69826799 const store_inst = self.builder.buildStore(operand, err_ptr);
6983 store_inst.setAlignment(Type.anyerror.abiAlignment(target));
6800 store_inst.setAlignment(Type.anyerror.abiAlignment(mod));
69846801 const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, "");
6985 var ptr_ty_payload: Type.Payload.ElemType = .{
6986 .base = .{ .tag = .single_mut_pointer },
6987 .data = payload_ty,
6988 };
6989 const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base);
6802 const payload_ptr_ty = try mod.singleMutPtrType(payload_ty);
69906803 // TODO store undef to payload_ptr
69916804 _ = payload_ptr;
69926805 _ = payload_ptr_ty;
......@@ -7021,20 +6834,20 @@ pub const FuncGen = struct {
70216834 }
70226835
70236836 fn airVectorStoreElem(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6837 const mod = self.dg.module;
70246838 const data = self.air.instructions.items(.data)[inst].vector_store_elem;
70256839 const extra = self.air.extraData(Air.Bin, data.payload).data;
70266840
70276841 const vector_ptr = try self.resolveInst(data.vector_ptr);
7028 const vector_ptr_ty = self.air.typeOf(data.vector_ptr);
6842 const vector_ptr_ty = self.typeOf(data.vector_ptr);
70296843 const index = try self.resolveInst(extra.lhs);
70306844 const operand = try self.resolveInst(extra.rhs);
70316845
70326846 const loaded_vector = blk: {
7033 const elem_llvm_ty = try self.dg.lowerType(vector_ptr_ty.childType());
6847 const elem_llvm_ty = try self.dg.lowerType(vector_ptr_ty.childType(mod));
70346848 const load_inst = self.builder.buildLoad(elem_llvm_ty, vector_ptr, "");
7035 const target = self.dg.module.getTarget();
7036 load_inst.setAlignment(vector_ptr_ty.ptrAlignment(target));
7037 load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr()));
6849 load_inst.setAlignment(vector_ptr_ty.ptrAlignment(mod));
6850 load_inst.setVolatile(llvm.Bool.fromBool(vector_ptr_ty.isVolatilePtr(mod)));
70386851 break :blk load_inst;
70396852 };
70406853 const modified_vector = self.builder.buildInsertElement(loaded_vector, operand, index, "");
......@@ -7043,24 +6856,26 @@ pub const FuncGen = struct {
70436856 }
70446857
70456858 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6859 const mod = self.dg.module;
70466860 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
70476861 const lhs = try self.resolveInst(bin_op.lhs);
70486862 const rhs = try self.resolveInst(bin_op.rhs);
7049 const scalar_ty = self.air.typeOfIndex(inst).scalarType();
6863 const scalar_ty = self.typeOfIndex(inst).scalarType(mod);
70506864
70516865 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmin, scalar_ty, 2, .{ lhs, rhs });
7052 if (scalar_ty.isSignedInt()) return self.builder.buildSMin(lhs, rhs, "");
6866 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSMin(lhs, rhs, "");
70536867 return self.builder.buildUMin(lhs, rhs, "");
70546868 }
70556869
70566870 fn airMax(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6871 const mod = self.dg.module;
70576872 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
70586873 const lhs = try self.resolveInst(bin_op.lhs);
70596874 const rhs = try self.resolveInst(bin_op.rhs);
7060 const scalar_ty = self.air.typeOfIndex(inst).scalarType();
6875 const scalar_ty = self.typeOfIndex(inst).scalarType(mod);
70616876
70626877 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.fmax, scalar_ty, 2, .{ lhs, rhs });
7063 if (scalar_ty.isSignedInt()) return self.builder.buildSMax(lhs, rhs, "");
6878 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSMax(lhs, rhs, "");
70646879 return self.builder.buildUMax(lhs, rhs, "");
70656880 }
70666881
......@@ -7069,7 +6884,7 @@ pub const FuncGen = struct {
70696884 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
70706885 const ptr = try self.resolveInst(bin_op.lhs);
70716886 const len = try self.resolveInst(bin_op.rhs);
7072 const inst_ty = self.air.typeOfIndex(inst);
6887 const inst_ty = self.typeOfIndex(inst);
70736888 const llvm_slice_ty = try self.dg.lowerType(inst_ty);
70746889
70756890 // In case of slicing a global, the result type looks something like `{ i8*, i64 }`
......@@ -7081,14 +6896,15 @@ pub const FuncGen = struct {
70816896 fn airAdd(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
70826897 self.builder.setFastMath(want_fast_math);
70836898
6899 const mod = self.dg.module;
70846900 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
70856901 const lhs = try self.resolveInst(bin_op.lhs);
70866902 const rhs = try self.resolveInst(bin_op.rhs);
7087 const inst_ty = self.air.typeOfIndex(inst);
7088 const scalar_ty = inst_ty.scalarType();
6903 const inst_ty = self.typeOfIndex(inst);
6904 const scalar_ty = inst_ty.scalarType(mod);
70896905
70906906 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.add, inst_ty, 2, .{ lhs, rhs });
7091 if (scalar_ty.isSignedInt()) return self.builder.buildNSWAdd(lhs, rhs, "");
6907 if (scalar_ty.isSignedInt(mod)) return self.builder.buildNSWAdd(lhs, rhs, "");
70926908 return self.builder.buildNUWAdd(lhs, rhs, "");
70936909 }
70946910
......@@ -7103,14 +6919,15 @@ pub const FuncGen = struct {
71036919 }
71046920
71056921 fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6922 const mod = self.dg.module;
71066923 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
71076924 const lhs = try self.resolveInst(bin_op.lhs);
71086925 const rhs = try self.resolveInst(bin_op.rhs);
7109 const inst_ty = self.air.typeOfIndex(inst);
7110 const scalar_ty = inst_ty.scalarType();
6926 const inst_ty = self.typeOfIndex(inst);
6927 const scalar_ty = inst_ty.scalarType(mod);
71116928
71126929 if (scalar_ty.isAnyFloat()) return self.todo("saturating float add", .{});
7113 if (scalar_ty.isSignedInt()) return self.builder.buildSAddSat(lhs, rhs, "");
6930 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSAddSat(lhs, rhs, "");
71146931
71156932 return self.builder.buildUAddSat(lhs, rhs, "");
71166933 }
......@@ -7118,14 +6935,15 @@ pub const FuncGen = struct {
71186935 fn airSub(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
71196936 self.builder.setFastMath(want_fast_math);
71206937
6938 const mod = self.dg.module;
71216939 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
71226940 const lhs = try self.resolveInst(bin_op.lhs);
71236941 const rhs = try self.resolveInst(bin_op.rhs);
7124 const inst_ty = self.air.typeOfIndex(inst);
7125 const scalar_ty = inst_ty.scalarType();
6942 const inst_ty = self.typeOfIndex(inst);
6943 const scalar_ty = inst_ty.scalarType(mod);
71266944
71276945 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.sub, inst_ty, 2, .{ lhs, rhs });
7128 if (scalar_ty.isSignedInt()) return self.builder.buildNSWSub(lhs, rhs, "");
6946 if (scalar_ty.isSignedInt(mod)) return self.builder.buildNSWSub(lhs, rhs, "");
71296947 return self.builder.buildNUWSub(lhs, rhs, "");
71306948 }
71316949
......@@ -7140,28 +6958,30 @@ pub const FuncGen = struct {
71406958 }
71416959
71426960 fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6961 const mod = self.dg.module;
71436962 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
71446963 const lhs = try self.resolveInst(bin_op.lhs);
71456964 const rhs = try self.resolveInst(bin_op.rhs);
7146 const inst_ty = self.air.typeOfIndex(inst);
7147 const scalar_ty = inst_ty.scalarType();
6965 const inst_ty = self.typeOfIndex(inst);
6966 const scalar_ty = inst_ty.scalarType(mod);
71486967
71496968 if (scalar_ty.isAnyFloat()) return self.todo("saturating float sub", .{});
7150 if (scalar_ty.isSignedInt()) return self.builder.buildSSubSat(lhs, rhs, "");
6969 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSSubSat(lhs, rhs, "");
71516970 return self.builder.buildUSubSat(lhs, rhs, "");
71526971 }
71536972
71546973 fn airMul(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
71556974 self.builder.setFastMath(want_fast_math);
71566975
6976 const mod = self.dg.module;
71576977 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
71586978 const lhs = try self.resolveInst(bin_op.lhs);
71596979 const rhs = try self.resolveInst(bin_op.rhs);
7160 const inst_ty = self.air.typeOfIndex(inst);
7161 const scalar_ty = inst_ty.scalarType();
6980 const inst_ty = self.typeOfIndex(inst);
6981 const scalar_ty = inst_ty.scalarType(mod);
71626982
71636983 if (scalar_ty.isAnyFloat()) return self.buildFloatOp(.mul, inst_ty, 2, .{ lhs, rhs });
7164 if (scalar_ty.isSignedInt()) return self.builder.buildNSWMul(lhs, rhs, "");
6984 if (scalar_ty.isSignedInt(mod)) return self.builder.buildNSWMul(lhs, rhs, "");
71656985 return self.builder.buildNUWMul(lhs, rhs, "");
71666986 }
71676987
......@@ -7176,14 +6996,15 @@ pub const FuncGen = struct {
71766996 }
71776997
71786998 fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
6999 const mod = self.dg.module;
71797000 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
71807001 const lhs = try self.resolveInst(bin_op.lhs);
71817002 const rhs = try self.resolveInst(bin_op.rhs);
7182 const inst_ty = self.air.typeOfIndex(inst);
7183 const scalar_ty = inst_ty.scalarType();
7003 const inst_ty = self.typeOfIndex(inst);
7004 const scalar_ty = inst_ty.scalarType(mod);
71847005
71857006 if (scalar_ty.isAnyFloat()) return self.todo("saturating float mul", .{});
7186 if (scalar_ty.isSignedInt()) return self.builder.buildSMulFixSat(lhs, rhs, "");
7007 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSMulFixSat(lhs, rhs, "");
71877008 return self.builder.buildUMulFixSat(lhs, rhs, "");
71887009 }
71897010
......@@ -7193,7 +7014,7 @@ pub const FuncGen = struct {
71937014 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
71947015 const lhs = try self.resolveInst(bin_op.lhs);
71957016 const rhs = try self.resolveInst(bin_op.rhs);
7196 const inst_ty = self.air.typeOfIndex(inst);
7017 const inst_ty = self.typeOfIndex(inst);
71977018
71987019 return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
71997020 }
......@@ -7201,39 +7022,40 @@ pub const FuncGen = struct {
72017022 fn airDivTrunc(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
72027023 self.builder.setFastMath(want_fast_math);
72037024
7025 const mod = self.dg.module;
72047026 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
72057027 const lhs = try self.resolveInst(bin_op.lhs);
72067028 const rhs = try self.resolveInst(bin_op.rhs);
7207 const inst_ty = self.air.typeOfIndex(inst);
7208 const scalar_ty = inst_ty.scalarType();
7029 const inst_ty = self.typeOfIndex(inst);
7030 const scalar_ty = inst_ty.scalarType(mod);
72097031
72107032 if (scalar_ty.isRuntimeFloat()) {
72117033 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
72127034 return self.buildFloatOp(.trunc, inst_ty, 1, .{result});
72137035 }
7214 if (scalar_ty.isSignedInt()) return self.builder.buildSDiv(lhs, rhs, "");
7036 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSDiv(lhs, rhs, "");
72157037 return self.builder.buildUDiv(lhs, rhs, "");
72167038 }
72177039
72187040 fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
72197041 self.builder.setFastMath(want_fast_math);
72207042
7043 const mod = self.dg.module;
72217044 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
72227045 const lhs = try self.resolveInst(bin_op.lhs);
72237046 const rhs = try self.resolveInst(bin_op.rhs);
7224 const inst_ty = self.air.typeOfIndex(inst);
7225 const scalar_ty = inst_ty.scalarType();
7047 const inst_ty = self.typeOfIndex(inst);
7048 const scalar_ty = inst_ty.scalarType(mod);
72267049
72277050 if (scalar_ty.isRuntimeFloat()) {
72287051 const result = try self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
72297052 return self.buildFloatOp(.floor, inst_ty, 1, .{result});
72307053 }
7231 if (scalar_ty.isSignedInt()) {
7232 const target = self.dg.module.getTarget();
7054 if (scalar_ty.isSignedInt(mod)) {
72337055 const inst_llvm_ty = try self.dg.lowerType(inst_ty);
7234 const scalar_bit_size_minus_one = scalar_ty.bitSize(target) - 1;
7235 const bit_size_minus_one = if (inst_ty.zigTypeTag() == .Vector) const_vector: {
7236 const vec_len = inst_ty.vectorLen();
7056 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
7057 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
7058 const vec_len = inst_ty.vectorLen(mod);
72377059 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
72387060
72397061 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
......@@ -7258,40 +7080,43 @@ pub const FuncGen = struct {
72587080 fn airDivExact(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
72597081 self.builder.setFastMath(want_fast_math);
72607082
7083 const mod = self.dg.module;
72617084 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
72627085 const lhs = try self.resolveInst(bin_op.lhs);
72637086 const rhs = try self.resolveInst(bin_op.rhs);
7264 const inst_ty = self.air.typeOfIndex(inst);
7265 const scalar_ty = inst_ty.scalarType();
7087 const inst_ty = self.typeOfIndex(inst);
7088 const scalar_ty = inst_ty.scalarType(mod);
72667089
72677090 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.div, inst_ty, 2, .{ lhs, rhs });
7268 if (scalar_ty.isSignedInt()) return self.builder.buildExactSDiv(lhs, rhs, "");
7091 if (scalar_ty.isSignedInt(mod)) return self.builder.buildExactSDiv(lhs, rhs, "");
72697092 return self.builder.buildExactUDiv(lhs, rhs, "");
72707093 }
72717094
72727095 fn airRem(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
72737096 self.builder.setFastMath(want_fast_math);
72747097
7098 const mod = self.dg.module;
72757099 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
72767100 const lhs = try self.resolveInst(bin_op.lhs);
72777101 const rhs = try self.resolveInst(bin_op.rhs);
7278 const inst_ty = self.air.typeOfIndex(inst);
7279 const scalar_ty = inst_ty.scalarType();
7102 const inst_ty = self.typeOfIndex(inst);
7103 const scalar_ty = inst_ty.scalarType(mod);
72807104
72817105 if (scalar_ty.isRuntimeFloat()) return self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
7282 if (scalar_ty.isSignedInt()) return self.builder.buildSRem(lhs, rhs, "");
7106 if (scalar_ty.isSignedInt(mod)) return self.builder.buildSRem(lhs, rhs, "");
72837107 return self.builder.buildURem(lhs, rhs, "");
72847108 }
72857109
72867110 fn airMod(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
72877111 self.builder.setFastMath(want_fast_math);
72887112
7113 const mod = self.dg.module;
72897114 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
72907115 const lhs = try self.resolveInst(bin_op.lhs);
72917116 const rhs = try self.resolveInst(bin_op.rhs);
7292 const inst_ty = self.air.typeOfIndex(inst);
7117 const inst_ty = self.typeOfIndex(inst);
72937118 const inst_llvm_ty = try self.dg.lowerType(inst_ty);
7294 const scalar_ty = inst_ty.scalarType();
7119 const scalar_ty = inst_ty.scalarType(mod);
72957120
72967121 if (scalar_ty.isRuntimeFloat()) {
72977122 const a = try self.buildFloatOp(.fmod, inst_ty, 2, .{ lhs, rhs });
......@@ -7301,11 +7126,10 @@ pub const FuncGen = struct {
73017126 const ltz = try self.buildFloatCmp(.lt, inst_ty, .{ lhs, zero });
73027127 return self.builder.buildSelect(ltz, c, a, "");
73037128 }
7304 if (scalar_ty.isSignedInt()) {
7305 const target = self.dg.module.getTarget();
7306 const scalar_bit_size_minus_one = scalar_ty.bitSize(target) - 1;
7307 const bit_size_minus_one = if (inst_ty.zigTypeTag() == .Vector) const_vector: {
7308 const vec_len = inst_ty.vectorLen();
7129 if (scalar_ty.isSignedInt(mod)) {
7130 const scalar_bit_size_minus_one = scalar_ty.bitSize(mod) - 1;
7131 const bit_size_minus_one = if (inst_ty.zigTypeTag(mod) == .Vector) const_vector: {
7132 const vec_len = inst_ty.vectorLen(mod);
73097133 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
73107134
73117135 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
......@@ -7328,13 +7152,14 @@ pub const FuncGen = struct {
73287152 }
73297153
73307154 fn airPtrAdd(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7155 const mod = self.dg.module;
73317156 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
73327157 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
73337158 const ptr = try self.resolveInst(bin_op.lhs);
73347159 const offset = try self.resolveInst(bin_op.rhs);
7335 const ptr_ty = self.air.typeOf(bin_op.lhs);
7336 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType());
7337 switch (ptr_ty.ptrSize()) {
7160 const ptr_ty = self.typeOf(bin_op.lhs);
7161 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType(mod));
7162 switch (ptr_ty.ptrSize(mod)) {
73387163 .One => {
73397164 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
73407165 const indices: [2]*llvm.Value = .{ self.context.intType(32).constNull(), offset };
......@@ -7353,14 +7178,15 @@ pub const FuncGen = struct {
73537178 }
73547179
73557180 fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7181 const mod = self.dg.module;
73567182 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
73577183 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
73587184 const ptr = try self.resolveInst(bin_op.lhs);
73597185 const offset = try self.resolveInst(bin_op.rhs);
73607186 const negative_offset = self.builder.buildNeg(offset, "");
7361 const ptr_ty = self.air.typeOf(bin_op.lhs);
7362 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType());
7363 switch (ptr_ty.ptrSize()) {
7187 const ptr_ty = self.typeOf(bin_op.lhs);
7188 const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType(mod));
7189 switch (ptr_ty.ptrSize(mod)) {
73647190 .One => {
73657191 // It's a pointer to an array, so according to LLVM we need an extra GEP index.
73667192 const indices: [2]*llvm.Value = .{
......@@ -7386,36 +7212,33 @@ pub const FuncGen = struct {
73867212 signed_intrinsic: []const u8,
73877213 unsigned_intrinsic: []const u8,
73887214 ) !?*llvm.Value {
7215 const mod = self.dg.module;
73897216 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
73907217 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
73917218
73927219 const lhs = try self.resolveInst(extra.lhs);
73937220 const rhs = try self.resolveInst(extra.rhs);
73947221
7395 const lhs_ty = self.air.typeOf(extra.lhs);
7396 const scalar_ty = lhs_ty.scalarType();
7397 const dest_ty = self.air.typeOfIndex(inst);
7222 const lhs_ty = self.typeOf(extra.lhs);
7223 const scalar_ty = lhs_ty.scalarType(mod);
7224 const dest_ty = self.typeOfIndex(inst);
73987225
7399 const intrinsic_name = if (scalar_ty.isSignedInt()) signed_intrinsic else unsigned_intrinsic;
7226 const intrinsic_name = if (scalar_ty.isSignedInt(mod)) signed_intrinsic else unsigned_intrinsic;
74007227
74017228 const llvm_lhs_ty = try self.dg.lowerType(lhs_ty);
74027229 const llvm_dest_ty = try self.dg.lowerType(dest_ty);
74037230
7404 const tg = self.dg.module.getTarget();
7405
74067231 const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty});
74077232 const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, "");
74087233
74097234 const result = self.builder.buildExtractValue(result_struct, 0, "");
74107235 const overflow_bit = self.builder.buildExtractValue(result_struct, 1, "");
74117236
7412 var ty_buf: Type.Payload.Pointer = undefined;
7413 const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?;
7414 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
7237 const result_index = llvmField(dest_ty, 0, mod).?.index;
7238 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
74157239
7416 if (isByRef(dest_ty)) {
7417 const target = self.dg.module.getTarget();
7418 const result_alignment = dest_ty.abiAlignment(target);
7240 if (isByRef(dest_ty, mod)) {
7241 const result_alignment = dest_ty.abiAlignment(mod);
74197242 const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment);
74207243 {
74217244 const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, "");
......@@ -7486,8 +7309,9 @@ pub const FuncGen = struct {
74867309 ty: Type,
74877310 params: [2]*llvm.Value,
74887311 ) !*llvm.Value {
7312 const mod = self.dg.module;
74897313 const target = self.dg.module.getTarget();
7490 const scalar_ty = ty.scalarType();
7314 const scalar_ty = ty.scalarType(mod);
74917315 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
74927316
74937317 if (intrinsicsAllowed(scalar_ty, target)) {
......@@ -7531,8 +7355,8 @@ pub const FuncGen = struct {
75317355 .gte => .SGE,
75327356 };
75337357
7534 if (ty.zigTypeTag() == .Vector) {
7535 const vec_len = ty.vectorLen();
7358 if (ty.zigTypeTag(mod) == .Vector) {
7359 const vec_len = ty.vectorLen(mod);
75367360 const vector_result_ty = llvm_i32.vectorType(vec_len);
75377361
75387362 var result = vector_result_ty.getUndef();
......@@ -7587,8 +7411,9 @@ pub const FuncGen = struct {
75877411 comptime params_len: usize,
75887412 params: [params_len]*llvm.Value,
75897413 ) !*llvm.Value {
7590 const target = self.dg.module.getTarget();
7591 const scalar_ty = ty.scalarType();
7414 const mod = self.dg.module;
7415 const target = mod.getTarget();
7416 const scalar_ty = ty.scalarType(mod);
75927417 const llvm_ty = try self.dg.lowerType(ty);
75937418 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
75947419
......@@ -7615,9 +7440,9 @@ pub const FuncGen = struct {
76157440 const one = int_llvm_ty.constInt(1, .False);
76167441 const shift_amt = int_llvm_ty.constInt(float_bits - 1, .False);
76177442 const sign_mask = one.constShl(shift_amt);
7618 const result = if (ty.zigTypeTag() == .Vector) blk: {
7619 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(), sign_mask, "");
7620 const cast_ty = int_llvm_ty.vectorType(ty.vectorLen());
7443 const result = if (ty.zigTypeTag(mod) == .Vector) blk: {
7444 const splat_sign_mask = self.builder.buildVectorSplat(ty.vectorLen(mod), sign_mask, "");
7445 const cast_ty = int_llvm_ty.vectorType(ty.vectorLen(mod));
76217446 const bitcasted_operand = self.builder.buildBitCast(params[0], cast_ty, "");
76227447 break :blk self.builder.buildXor(bitcasted_operand, splat_sign_mask, "");
76237448 } else blk: {
......@@ -7662,9 +7487,9 @@ pub const FuncGen = struct {
76627487 .libc => |fn_name| b: {
76637488 const param_types = [3]*llvm.Type{ scalar_llvm_ty, scalar_llvm_ty, scalar_llvm_ty };
76647489 const libc_fn = self.getLibcFunction(fn_name, param_types[0..params.len], scalar_llvm_ty);
7665 if (ty.zigTypeTag() == .Vector) {
7490 if (ty.zigTypeTag(mod) == .Vector) {
76667491 const result = llvm_ty.getUndef();
7667 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen());
7492 return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(mod));
76687493 }
76697494
76707495 break :b libc_fn;
......@@ -7681,47 +7506,44 @@ pub const FuncGen = struct {
76817506 const mulend2 = try self.resolveInst(extra.rhs);
76827507 const addend = try self.resolveInst(pl_op.operand);
76837508
7684 const ty = self.air.typeOfIndex(inst);
7509 const ty = self.typeOfIndex(inst);
76857510 return self.buildFloatOp(.fma, ty, 3, .{ mulend1, mulend2, addend });
76867511 }
76877512
76887513 fn airShlWithOverflow(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7514 const mod = self.dg.module;
76897515 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
76907516 const extra = self.air.extraData(Air.Bin, ty_pl.payload).data;
76917517
76927518 const lhs = try self.resolveInst(extra.lhs);
76937519 const rhs = try self.resolveInst(extra.rhs);
76947520
7695 const lhs_ty = self.air.typeOf(extra.lhs);
7696 const rhs_ty = self.air.typeOf(extra.rhs);
7697 const lhs_scalar_ty = lhs_ty.scalarType();
7698 const rhs_scalar_ty = rhs_ty.scalarType();
7521 const lhs_ty = self.typeOf(extra.lhs);
7522 const rhs_ty = self.typeOf(extra.rhs);
7523 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7524 const rhs_scalar_ty = rhs_ty.scalarType(mod);
76997525
7700 const dest_ty = self.air.typeOfIndex(inst);
7526 const dest_ty = self.typeOfIndex(inst);
77017527 const llvm_dest_ty = try self.dg.lowerType(dest_ty);
77027528
7703 const tg = self.dg.module.getTarget();
7704
7705 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
7529 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
77067530 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")
77077531 else
77087532 rhs;
77097533
77107534 const result = self.builder.buildShl(lhs, casted_rhs, "");
7711 const reconstructed = if (lhs_scalar_ty.isSignedInt())
7535 const reconstructed = if (lhs_scalar_ty.isSignedInt(mod))
77127536 self.builder.buildAShr(result, casted_rhs, "")
77137537 else
77147538 self.builder.buildLShr(result, casted_rhs, "");
77157539
77167540 const overflow_bit = self.builder.buildICmp(.NE, lhs, reconstructed, "");
77177541
7718 var ty_buf: Type.Payload.Pointer = undefined;
7719 const result_index = llvmFieldIndex(dest_ty, 0, tg, &ty_buf).?;
7720 const overflow_index = llvmFieldIndex(dest_ty, 1, tg, &ty_buf).?;
7542 const result_index = llvmField(dest_ty, 0, mod).?.index;
7543 const overflow_index = llvmField(dest_ty, 1, mod).?.index;
77217544
7722 if (isByRef(dest_ty)) {
7723 const target = self.dg.module.getTarget();
7724 const result_alignment = dest_ty.abiAlignment(target);
7545 if (isByRef(dest_ty, mod)) {
7546 const result_alignment = dest_ty.abiAlignment(mod);
77257547 const alloca_inst = self.buildAlloca(llvm_dest_ty, result_alignment);
77267548 {
77277549 const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, "");
......@@ -7763,40 +7585,38 @@ pub const FuncGen = struct {
77637585 }
77647586
77657587 fn airShlExact(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7588 const mod = self.dg.module;
77667589 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
77677590
77687591 const lhs = try self.resolveInst(bin_op.lhs);
77697592 const rhs = try self.resolveInst(bin_op.rhs);
77707593
7771 const lhs_ty = self.air.typeOf(bin_op.lhs);
7772 const rhs_ty = self.air.typeOf(bin_op.rhs);
7773 const lhs_scalar_ty = lhs_ty.scalarType();
7774 const rhs_scalar_ty = rhs_ty.scalarType();
7775
7776 const tg = self.dg.module.getTarget();
7594 const lhs_ty = self.typeOf(bin_op.lhs);
7595 const rhs_ty = self.typeOf(bin_op.rhs);
7596 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7597 const rhs_scalar_ty = rhs_ty.scalarType(mod);
77777598
7778 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
7599 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
77797600 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")
77807601 else
77817602 rhs;
7782 if (lhs_scalar_ty.isSignedInt()) return self.builder.buildNSWShl(lhs, casted_rhs, "");
7603 if (lhs_scalar_ty.isSignedInt(mod)) return self.builder.buildNSWShl(lhs, casted_rhs, "");
77837604 return self.builder.buildNUWShl(lhs, casted_rhs, "");
77847605 }
77857606
77867607 fn airShl(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7608 const mod = self.dg.module;
77877609 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
77887610
77897611 const lhs = try self.resolveInst(bin_op.lhs);
77907612 const rhs = try self.resolveInst(bin_op.rhs);
77917613
7792 const lhs_type = self.air.typeOf(bin_op.lhs);
7793 const rhs_type = self.air.typeOf(bin_op.rhs);
7794 const lhs_scalar_ty = lhs_type.scalarType();
7795 const rhs_scalar_ty = rhs_type.scalarType();
7796
7797 const tg = self.dg.module.getTarget();
7614 const lhs_type = self.typeOf(bin_op.lhs);
7615 const rhs_type = self.typeOf(bin_op.rhs);
7616 const lhs_scalar_ty = lhs_type.scalarType(mod);
7617 const rhs_scalar_ty = rhs_type.scalarType(mod);
77987618
7799 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
7619 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
78007620 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_type), "")
78017621 else
78027622 rhs;
......@@ -7804,24 +7624,24 @@ pub const FuncGen = struct {
78047624 }
78057625
78067626 fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7627 const mod = self.dg.module;
78077628 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78087629
78097630 const lhs = try self.resolveInst(bin_op.lhs);
78107631 const rhs = try self.resolveInst(bin_op.rhs);
78117632
7812 const lhs_ty = self.air.typeOf(bin_op.lhs);
7813 const rhs_ty = self.air.typeOf(bin_op.rhs);
7814 const lhs_scalar_ty = lhs_ty.scalarType();
7815 const rhs_scalar_ty = rhs_ty.scalarType();
7816 const tg = self.dg.module.getTarget();
7817 const lhs_bits = lhs_scalar_ty.bitSize(tg);
7633 const lhs_ty = self.typeOf(bin_op.lhs);
7634 const rhs_ty = self.typeOf(bin_op.rhs);
7635 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7636 const rhs_scalar_ty = rhs_ty.scalarType(mod);
7637 const lhs_bits = lhs_scalar_ty.bitSize(mod);
78187638
7819 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_bits)
7639 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_bits)
78207640 self.builder.buildZExt(rhs, lhs.typeOf(), "")
78217641 else
78227642 rhs;
78237643
7824 const result = if (lhs_scalar_ty.isSignedInt())
7644 const result = if (lhs_scalar_ty.isSignedInt(mod))
78257645 self.builder.buildSShlSat(lhs, casted_rhs, "")
78267646 else
78277647 self.builder.buildUShlSat(lhs, casted_rhs, "");
......@@ -7834,8 +7654,8 @@ pub const FuncGen = struct {
78347654 const lhs_scalar_llvm_ty = try self.dg.lowerType(lhs_scalar_ty);
78357655 const bits = lhs_scalar_llvm_ty.constInt(lhs_bits, .False);
78367656 const lhs_max = lhs_scalar_llvm_ty.constAllOnes();
7837 if (rhs_ty.zigTypeTag() == .Vector) {
7838 const vec_len = rhs_ty.vectorLen();
7657 if (rhs_ty.zigTypeTag(mod) == .Vector) {
7658 const vec_len = rhs_ty.vectorLen(mod);
78397659 const bits_vec = self.builder.buildVectorSplat(vec_len, bits, "");
78407660 const lhs_max_vec = self.builder.buildVectorSplat(vec_len, lhs_max, "");
78417661 const in_range = self.builder.buildICmp(.ULT, rhs, bits_vec, "");
......@@ -7847,23 +7667,22 @@ pub const FuncGen = struct {
78477667 }
78487668
78497669 fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) !?*llvm.Value {
7670 const mod = self.dg.module;
78507671 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
78517672
78527673 const lhs = try self.resolveInst(bin_op.lhs);
78537674 const rhs = try self.resolveInst(bin_op.rhs);
78547675
7855 const lhs_ty = self.air.typeOf(bin_op.lhs);
7856 const rhs_ty = self.air.typeOf(bin_op.rhs);
7857 const lhs_scalar_ty = lhs_ty.scalarType();
7858 const rhs_scalar_ty = rhs_ty.scalarType();
7676 const lhs_ty = self.typeOf(bin_op.lhs);
7677 const rhs_ty = self.typeOf(bin_op.rhs);
7678 const lhs_scalar_ty = lhs_ty.scalarType(mod);
7679 const rhs_scalar_ty = rhs_ty.scalarType(mod);
78597680
7860 const tg = self.dg.module.getTarget();
7861
7862 const casted_rhs = if (rhs_scalar_ty.bitSize(tg) < lhs_scalar_ty.bitSize(tg))
7681 const casted_rhs = if (rhs_scalar_ty.bitSize(mod) < lhs_scalar_ty.bitSize(mod))
78637682 self.builder.buildZExt(rhs, try self.dg.lowerType(lhs_ty), "")
78647683 else
78657684 rhs;
7866 const is_signed_int = lhs_scalar_ty.isSignedInt();
7685 const is_signed_int = lhs_scalar_ty.isSignedInt(mod);
78677686
78687687 if (is_exact) {
78697688 if (is_signed_int) {
......@@ -7881,14 +7700,14 @@ pub const FuncGen = struct {
78817700 }
78827701
78837702 fn airIntCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7884 const target = self.dg.module.getTarget();
7703 const mod = self.dg.module;
78857704 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7886 const dest_ty = self.air.typeOfIndex(inst);
7887 const dest_info = dest_ty.intInfo(target);
7705 const dest_ty = self.typeOfIndex(inst);
7706 const dest_info = dest_ty.intInfo(mod);
78887707 const dest_llvm_ty = try self.dg.lowerType(dest_ty);
78897708 const operand = try self.resolveInst(ty_op.operand);
7890 const operand_ty = self.air.typeOf(ty_op.operand);
7891 const operand_info = operand_ty.intInfo(target);
7709 const operand_ty = self.typeOf(ty_op.operand);
7710 const operand_info = operand_ty.intInfo(mod);
78927711
78937712 if (operand_info.bits < dest_info.bits) {
78947713 switch (operand_info.signedness) {
......@@ -7905,16 +7724,17 @@ pub const FuncGen = struct {
79057724 fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
79067725 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
79077726 const operand = try self.resolveInst(ty_op.operand);
7908 const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
7727 const dest_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst));
79097728 return self.builder.buildTrunc(operand, dest_llvm_ty, "");
79107729 }
79117730
79127731 fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7732 const mod = self.dg.module;
79137733 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
79147734 const operand = try self.resolveInst(ty_op.operand);
7915 const operand_ty = self.air.typeOf(ty_op.operand);
7916 const dest_ty = self.air.typeOfIndex(inst);
7917 const target = self.dg.module.getTarget();
7735 const operand_ty = self.typeOf(ty_op.operand);
7736 const dest_ty = self.typeOfIndex(inst);
7737 const target = mod.getTarget();
79187738 const dest_bits = dest_ty.floatBits(target);
79197739 const src_bits = operand_ty.floatBits(target);
79207740
......@@ -7939,11 +7759,12 @@ pub const FuncGen = struct {
79397759 }
79407760
79417761 fn airFpext(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7762 const mod = self.dg.module;
79427763 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
79437764 const operand = try self.resolveInst(ty_op.operand);
7944 const operand_ty = self.air.typeOf(ty_op.operand);
7945 const dest_ty = self.air.typeOfIndex(inst);
7946 const target = self.dg.module.getTarget();
7765 const operand_ty = self.typeOf(ty_op.operand);
7766 const dest_ty = self.typeOfIndex(inst);
7767 const target = mod.getTarget();
79477768 const dest_bits = dest_ty.floatBits(target);
79487769 const src_bits = operand_ty.floatBits(target);
79497770
......@@ -7970,25 +7791,25 @@ pub const FuncGen = struct {
79707791 fn airPtrToInt(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
79717792 const un_op = self.air.instructions.items(.data)[inst].un_op;
79727793 const operand = try self.resolveInst(un_op);
7973 const ptr_ty = self.air.typeOf(un_op);
7794 const ptr_ty = self.typeOf(un_op);
79747795 const operand_ptr = self.sliceOrArrayPtr(operand, ptr_ty);
7975 const dest_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst));
7796 const dest_llvm_ty = try self.dg.lowerType(self.typeOfIndex(inst));
79767797 return self.builder.buildPtrToInt(operand_ptr, dest_llvm_ty, "");
79777798 }
79787799
79797800 fn airBitCast(self: *FuncGen, inst: Air.Inst.Index) !*llvm.Value {
79807801 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
7981 const operand_ty = self.air.typeOf(ty_op.operand);
7982 const inst_ty = self.air.typeOfIndex(inst);
7802 const operand_ty = self.typeOf(ty_op.operand);
7803 const inst_ty = self.typeOfIndex(inst);
79837804 const operand = try self.resolveInst(ty_op.operand);
79847805 return self.bitCast(operand, operand_ty, inst_ty);
79857806 }
79867807
79877808 fn bitCast(self: *FuncGen, operand: *llvm.Value, operand_ty: Type, inst_ty: Type) !*llvm.Value {
7988 const operand_is_ref = isByRef(operand_ty);
7989 const result_is_ref = isByRef(inst_ty);
7809 const mod = self.dg.module;
7810 const operand_is_ref = isByRef(operand_ty, mod);
7811 const result_is_ref = isByRef(inst_ty, mod);
79907812 const llvm_dest_ty = try self.dg.lowerType(inst_ty);
7991 const target = self.dg.module.getTarget();
79927813
79937814 if (operand_is_ref and result_is_ref) {
79947815 // They are both pointers, so just return the same opaque pointer :)
......@@ -8001,27 +7822,27 @@ pub const FuncGen = struct {
80017822 return self.builder.buildZExtOrBitCast(operand, llvm_dest_ty, "");
80027823 }
80037824
8004 if (operand_ty.zigTypeTag() == .Int and inst_ty.isPtrAtRuntime()) {
7825 if (operand_ty.zigTypeTag(mod) == .Int and inst_ty.isPtrAtRuntime(mod)) {
80057826 return self.builder.buildIntToPtr(operand, llvm_dest_ty, "");
80067827 }
80077828
8008 if (operand_ty.zigTypeTag() == .Vector and inst_ty.zigTypeTag() == .Array) {
8009 const elem_ty = operand_ty.childType();
7829 if (operand_ty.zigTypeTag(mod) == .Vector and inst_ty.zigTypeTag(mod) == .Array) {
7830 const elem_ty = operand_ty.childType(mod);
80107831 if (!result_is_ref) {
80117832 return self.dg.todo("implement bitcast vector to non-ref array", .{});
80127833 }
80137834 const array_ptr = self.buildAlloca(llvm_dest_ty, null);
8014 const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8;
7835 const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8;
80157836 if (bitcast_ok) {
80167837 const llvm_store = self.builder.buildStore(operand, array_ptr);
8017 llvm_store.setAlignment(inst_ty.abiAlignment(target));
7838 llvm_store.setAlignment(inst_ty.abiAlignment(mod));
80187839 } else {
80197840 // If the ABI size of the element type is not evenly divisible by size in bits;
80207841 // a simple bitcast will not work, and we fall back to extractelement.
80217842 const llvm_usize = try self.dg.lowerType(Type.usize);
80227843 const llvm_u32 = self.context.intType(32);
80237844 const zero = llvm_usize.constNull();
8024 const vector_len = operand_ty.arrayLen();
7845 const vector_len = operand_ty.arrayLen(mod);
80257846 var i: u64 = 0;
80267847 while (i < vector_len) : (i += 1) {
80277848 const index_usize = llvm_usize.constInt(i, .False);
......@@ -8033,19 +7854,19 @@ pub const FuncGen = struct {
80337854 }
80347855 }
80357856 return array_ptr;
8036 } else if (operand_ty.zigTypeTag() == .Array and inst_ty.zigTypeTag() == .Vector) {
8037 const elem_ty = operand_ty.childType();
7857 } else if (operand_ty.zigTypeTag(mod) == .Array and inst_ty.zigTypeTag(mod) == .Vector) {
7858 const elem_ty = operand_ty.childType(mod);
80387859 const llvm_vector_ty = try self.dg.lowerType(inst_ty);
80397860 if (!operand_is_ref) {
80407861 return self.dg.todo("implement bitcast non-ref array to vector", .{});
80417862 }
80427863
8043 const bitcast_ok = elem_ty.bitSize(target) == elem_ty.abiSize(target) * 8;
7864 const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8;
80447865 if (bitcast_ok) {
80457866 const vector = self.builder.buildLoad(llvm_vector_ty, operand, "");
80467867 // The array is aligned to the element's alignment, while the vector might have a completely
80477868 // different alignment. This means we need to enforce the alignment of this load.
8048 vector.setAlignment(elem_ty.abiAlignment(target));
7869 vector.setAlignment(elem_ty.abiAlignment(mod));
80497870 return vector;
80507871 } else {
80517872 // If the ABI size of the element type is not evenly divisible by size in bits;
......@@ -8055,7 +7876,7 @@ pub const FuncGen = struct {
80557876 const llvm_usize = try self.dg.lowerType(Type.usize);
80567877 const llvm_u32 = self.context.intType(32);
80577878 const zero = llvm_usize.constNull();
8058 const vector_len = operand_ty.arrayLen();
7879 const vector_len = operand_ty.arrayLen(mod);
80597880 var vector = llvm_vector_ty.getUndef();
80607881 var i: u64 = 0;
80617882 while (i < vector_len) : (i += 1) {
......@@ -8073,12 +7894,12 @@ pub const FuncGen = struct {
80737894
80747895 if (operand_is_ref) {
80757896 const load_inst = self.builder.buildLoad(llvm_dest_ty, operand, "");
8076 load_inst.setAlignment(operand_ty.abiAlignment(target));
7897 load_inst.setAlignment(operand_ty.abiAlignment(mod));
80777898 return load_inst;
80787899 }
80797900
80807901 if (result_is_ref) {
8081 const alignment = @max(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target));
7902 const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod));
80827903 const result_ptr = self.buildAlloca(llvm_dest_ty, alignment);
80837904 const store_inst = self.builder.buildStore(operand, result_ptr);
80847905 store_inst.setAlignment(alignment);
......@@ -8089,7 +7910,7 @@ pub const FuncGen = struct {
80897910 // Both our operand and our result are values, not pointers,
80907911 // but LLVM won't let us bitcast struct values.
80917912 // Therefore, we store operand to alloca, then load for result.
8092 const alignment = @max(operand_ty.abiAlignment(target), inst_ty.abiAlignment(target));
7913 const alignment = @max(operand_ty.abiAlignment(mod), inst_ty.abiAlignment(mod));
80937914 const result_ptr = self.buildAlloca(llvm_dest_ty, alignment);
80947915 const store_inst = self.builder.buildStore(operand, result_ptr);
80957916 store_inst.setAlignment(alignment);
......@@ -8108,22 +7929,23 @@ pub const FuncGen = struct {
81087929 }
81097930
81107931 fn airArg(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
7932 const mod = self.dg.module;
81117933 const arg_val = self.args[self.arg_index];
81127934 self.arg_index += 1;
81137935
8114 const inst_ty = self.air.typeOfIndex(inst);
7936 const inst_ty = self.typeOfIndex(inst);
81157937 if (self.dg.object.di_builder) |dib| {
81167938 if (needDbgVarWorkaround(self.dg)) {
81177939 return arg_val;
81187940 }
81197941
81207942 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
8121 const func = self.dg.decl.getFunction().?;
8122 const lbrace_line = self.dg.module.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
7943 const func = self.dg.decl.getOwnedFunction(mod).?;
7944 const lbrace_line = mod.declPtr(func.owner_decl).src_line + func.lbrace_line + 1;
81237945 const lbrace_col = func.lbrace_column + 1;
81247946 const di_local_var = dib.createParameterVariable(
81257947 self.di_scope.?,
8126 func.getParamName(self.dg.module, src_index).ptr, // TODO test 0 bit args
7948 func.getParamName(mod, src_index).ptr, // TODO test 0 bit args
81277949 self.di_file.?,
81287950 lbrace_line,
81297951 try self.dg.object.lowerDebugType(inst_ty, .full),
......@@ -8134,10 +7956,10 @@ pub const FuncGen = struct {
81347956
81357957 const debug_loc = llvm.getDebugLoc(lbrace_line, lbrace_col, self.di_scope.?, null);
81367958 const insert_block = self.builder.getInsertBlock();
8137 if (isByRef(inst_ty)) {
7959 if (isByRef(inst_ty, mod)) {
81387960 _ = dib.insertDeclareAtEnd(arg_val, di_local_var, debug_loc, insert_block);
81397961 } else if (self.dg.module.comp.bin_file.options.optimize_mode == .Debug) {
8140 const alignment = inst_ty.abiAlignment(self.dg.module.getTarget());
7962 const alignment = inst_ty.abiAlignment(mod);
81417963 const alloca = self.buildAlloca(arg_val.typeOf(), alignment);
81427964 const store_inst = self.builder.buildStore(arg_val, alloca);
81437965 store_inst.setAlignment(alignment);
......@@ -8151,24 +7973,24 @@ pub const FuncGen = struct {
81517973 }
81527974
81537975 fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8154 const ptr_ty = self.air.typeOfIndex(inst);
8155 const pointee_type = ptr_ty.childType();
8156 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);
7976 const mod = self.dg.module;
7977 const ptr_ty = self.typeOfIndex(inst);
7978 const pointee_type = ptr_ty.childType(mod);
7979 if (!pointee_type.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty);
81577980
81587981 const pointee_llvm_ty = try self.dg.lowerType(pointee_type);
8159 const target = self.dg.module.getTarget();
8160 const alignment = ptr_ty.ptrAlignment(target);
7982 const alignment = ptr_ty.ptrAlignment(mod);
81617983 return self.buildAlloca(pointee_llvm_ty, alignment);
81627984 }
81637985
81647986 fn airRetPtr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8165 const ptr_ty = self.air.typeOfIndex(inst);
8166 const ret_ty = ptr_ty.childType();
8167 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return self.dg.lowerPtrToVoid(ptr_ty);
7987 const mod = self.dg.module;
7988 const ptr_ty = self.typeOfIndex(inst);
7989 const ret_ty = ptr_ty.childType(mod);
7990 if (!ret_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return self.dg.lowerPtrToVoid(ptr_ty);
81687991 if (self.ret_ptr) |ret_ptr| return ret_ptr;
81697992 const ret_llvm_ty = try self.dg.lowerType(ret_ty);
8170 const target = self.dg.module.getTarget();
8171 return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(target));
7993 return self.buildAlloca(ret_llvm_ty, ptr_ty.ptrAlignment(mod));
81727994 }
81737995
81747996 /// Use this instead of builder.buildAlloca, because this function makes sure to
......@@ -8178,12 +8000,13 @@ pub const FuncGen = struct {
81788000 }
81798001
81808002 fn airStore(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {
8003 const mod = self.dg.module;
81818004 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
81828005 const dest_ptr = try self.resolveInst(bin_op.lhs);
8183 const ptr_ty = self.air.typeOf(bin_op.lhs);
8184 const operand_ty = ptr_ty.childType();
8006 const ptr_ty = self.typeOf(bin_op.lhs);
8007 const operand_ty = ptr_ty.childType(mod);
81858008
8186 const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
8009 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
81878010 if (val_is_undef) {
81888011 // Even if safety is disabled, we still emit a memset to undefined since it conveys
81898012 // extra information to LLVM. However, safety makes the difference between using
......@@ -8193,13 +8016,12 @@ pub const FuncGen = struct {
81938016 u8_llvm_ty.constInt(0xaa, .False)
81948017 else
81958018 u8_llvm_ty.getUndef();
8196 const target = self.dg.module.getTarget();
8197 const operand_size = operand_ty.abiSize(target);
8019 const operand_size = operand_ty.abiSize(mod);
81988020 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
81998021 const len = usize_llvm_ty.constInt(operand_size, .False);
8200 const dest_ptr_align = ptr_ty.ptrAlignment(target);
8201 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr());
8202 if (safety and self.dg.module.comp.bin_file.options.valgrind) {
8022 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
8023 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, ptr_ty.isVolatilePtr(mod));
8024 if (safety and mod.comp.bin_file.options.valgrind) {
82038025 self.valgrindMarkUndef(dest_ptr, len);
82048026 }
82058027 return null;
......@@ -8217,8 +8039,10 @@ pub const FuncGen = struct {
82178039 ///
82188040 /// The first instruction of `body_tail` is the one whose copy we want to elide.
82198041 fn canElideLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) bool {
8042 const mod = fg.dg.module;
8043 const ip = &mod.intern_pool;
82208044 for (body_tail[1..]) |body_inst| {
8221 switch (fg.liveness.categorizeOperand(fg.air, body_inst, body_tail[0])) {
8045 switch (fg.liveness.categorizeOperand(fg.air, body_inst, body_tail[0], ip)) {
82228046 .none => continue,
82238047 .write, .noret, .complex => return false,
82248048 .tomb => return true,
......@@ -8230,14 +8054,15 @@ pub const FuncGen = struct {
82308054 }
82318055
82328056 fn airLoad(fg: *FuncGen, body_tail: []const Air.Inst.Index) !?*llvm.Value {
8057 const mod = fg.dg.module;
82338058 const inst = body_tail[0];
82348059 const ty_op = fg.air.instructions.items(.data)[inst].ty_op;
8235 const ptr_ty = fg.air.typeOf(ty_op.operand);
8236 const ptr_info = ptr_ty.ptrInfo().data;
8060 const ptr_ty = fg.typeOf(ty_op.operand);
8061 const ptr_info = ptr_ty.ptrInfo(mod);
82378062 const ptr = try fg.resolveInst(ty_op.operand);
82388063
82398064 elide: {
8240 if (!isByRef(ptr_info.pointee_type)) break :elide;
8065 if (!isByRef(ptr_info.pointee_type, mod)) break :elide;
82418066 if (!canElideLoad(fg, body_tail)) break :elide;
82428067 return ptr;
82438068 }
......@@ -8261,8 +8086,9 @@ pub const FuncGen = struct {
82618086
82628087 fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
82638088 _ = inst;
8089 const mod = self.dg.module;
82648090 const llvm_usize = try self.dg.lowerType(Type.usize);
8265 const target = self.dg.module.getTarget();
8091 const target = mod.getTarget();
82668092 if (!target_util.supportsReturnAddress(target)) {
82678093 // https://github.com/ziglang/zig/issues/11946
82688094 return llvm_usize.constNull();
......@@ -8301,16 +8127,17 @@ pub const FuncGen = struct {
83018127 }
83028128
83038129 fn airCmpxchg(self: *FuncGen, inst: Air.Inst.Index, is_weak: bool) !?*llvm.Value {
8130 const mod = self.dg.module;
83048131 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
83058132 const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data;
83068133 const ptr = try self.resolveInst(extra.ptr);
83078134 var expected_value = try self.resolveInst(extra.expected_value);
83088135 var new_value = try self.resolveInst(extra.new_value);
8309 const operand_ty = self.air.typeOf(extra.ptr).elemType();
8136 const operand_ty = self.typeOf(extra.ptr).childType(mod);
83108137 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);
83118138 if (opt_abi_ty) |abi_ty| {
83128139 // operand needs widening and truncating
8313 if (operand_ty.isSignedInt()) {
8140 if (operand_ty.isSignedInt(mod)) {
83148141 expected_value = self.builder.buildSExt(expected_value, abi_ty, "");
83158142 new_value = self.builder.buildSExt(new_value, abi_ty, "");
83168143 } else {
......@@ -8328,7 +8155,7 @@ pub const FuncGen = struct {
83288155 );
83298156 result.setWeak(llvm.Bool.fromBool(is_weak));
83308157
8331 const optional_ty = self.air.typeOfIndex(inst);
8158 const optional_ty = self.typeOfIndex(inst);
83328159
83338160 var payload = self.builder.buildExtractValue(result, 0, "");
83348161 if (opt_abi_ty != null) {
......@@ -8336,7 +8163,7 @@ pub const FuncGen = struct {
83368163 }
83378164 const success_bit = self.builder.buildExtractValue(result, 1, "");
83388165
8339 if (optional_ty.optionalReprIsPayload()) {
8166 if (optional_ty.optionalReprIsPayload(mod)) {
83408167 return self.builder.buildSelect(success_bit, payload.typeOf().constNull(), payload, "");
83418168 }
83428169
......@@ -8347,13 +8174,14 @@ pub const FuncGen = struct {
83478174 }
83488175
83498176 fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8177 const mod = self.dg.module;
83508178 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
83518179 const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data;
83528180 const ptr = try self.resolveInst(pl_op.operand);
8353 const ptr_ty = self.air.typeOf(pl_op.operand);
8354 const operand_ty = ptr_ty.elemType();
8181 const ptr_ty = self.typeOf(pl_op.operand);
8182 const operand_ty = ptr_ty.childType(mod);
83558183 const operand = try self.resolveInst(extra.operand);
8356 const is_signed_int = operand_ty.isSignedInt();
8184 const is_signed_int = operand_ty.isSignedInt(mod);
83578185 const is_float = operand_ty.isRuntimeFloat();
83588186 const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float);
83598187 const ordering = toLlvmAtomicOrdering(extra.ordering());
......@@ -8402,17 +8230,17 @@ pub const FuncGen = struct {
84028230 }
84038231
84048232 fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8233 const mod = self.dg.module;
84058234 const atomic_load = self.air.instructions.items(.data)[inst].atomic_load;
84068235 const ptr = try self.resolveInst(atomic_load.ptr);
8407 const ptr_ty = self.air.typeOf(atomic_load.ptr);
8408 const ptr_info = ptr_ty.ptrInfo().data;
8236 const ptr_ty = self.typeOf(atomic_load.ptr);
8237 const ptr_info = ptr_ty.ptrInfo(mod);
84098238 const elem_ty = ptr_info.pointee_type;
8410 if (!elem_ty.hasRuntimeBitsIgnoreComptime())
8239 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod))
84118240 return null;
84128241 const ordering = toLlvmAtomicOrdering(atomic_load.order);
84138242 const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false);
8414 const target = self.dg.module.getTarget();
8415 const ptr_alignment = ptr_info.alignment(target);
8243 const ptr_alignment = ptr_info.alignment(mod);
84168244 const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile");
84178245 const elem_llvm_ty = try self.dg.lowerType(elem_ty);
84188246
......@@ -8436,17 +8264,18 @@ pub const FuncGen = struct {
84368264 inst: Air.Inst.Index,
84378265 ordering: llvm.AtomicOrdering,
84388266 ) !?*llvm.Value {
8267 const mod = self.dg.module;
84398268 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8440 const ptr_ty = self.air.typeOf(bin_op.lhs);
8441 const operand_ty = ptr_ty.childType();
8442 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime()) return null;
8269 const ptr_ty = self.typeOf(bin_op.lhs);
8270 const operand_ty = ptr_ty.childType(mod);
8271 if (!operand_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return null;
84438272 const ptr = try self.resolveInst(bin_op.lhs);
84448273 var element = try self.resolveInst(bin_op.rhs);
84458274 const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false);
84468275
84478276 if (opt_abi_ty) |abi_ty| {
84488277 // operand needs widening
8449 if (operand_ty.isSignedInt()) {
8278 if (operand_ty.isSignedInt(mod)) {
84508279 element = self.builder.buildSExt(element, abi_ty, "");
84518280 } else {
84528281 element = self.builder.buildZExt(element, abi_ty, "");
......@@ -8457,19 +8286,19 @@ pub const FuncGen = struct {
84578286 }
84588287
84598288 fn airMemset(self: *FuncGen, inst: Air.Inst.Index, safety: bool) !?*llvm.Value {
8289 const mod = self.dg.module;
84608290 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
84618291 const dest_slice = try self.resolveInst(bin_op.lhs);
8462 const ptr_ty = self.air.typeOf(bin_op.lhs);
8463 const elem_ty = self.air.typeOf(bin_op.rhs);
8464 const module = self.dg.module;
8465 const target = module.getTarget();
8466 const dest_ptr_align = ptr_ty.ptrAlignment(target);
8292 const ptr_ty = self.typeOf(bin_op.lhs);
8293 const elem_ty = self.typeOf(bin_op.rhs);
8294 const target = mod.getTarget();
8295 const dest_ptr_align = ptr_ty.ptrAlignment(mod);
84678296 const u8_llvm_ty = self.context.intType(8);
84688297 const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty);
8469 const is_volatile = ptr_ty.isVolatilePtr();
8298 const is_volatile = ptr_ty.isVolatilePtr(mod);
84708299
8471 if (self.air.value(bin_op.rhs)) |elem_val| {
8472 if (elem_val.isUndefDeep()) {
8300 if (try self.air.value(bin_op.rhs, mod)) |elem_val| {
8301 if (elem_val.isUndefDeep(mod)) {
84738302 // Even if safety is disabled, we still emit a memset to undefined since it conveys
84748303 // extra information to LLVM. However, safety makes the difference between using
84758304 // 0xaa or actual undefined for the fill byte.
......@@ -8480,7 +8309,7 @@ pub const FuncGen = struct {
84808309 const len = self.sliceOrArrayLenInBytes(dest_slice, ptr_ty);
84818310 _ = self.builder.buildMemSet(dest_ptr, fill_byte, len, dest_ptr_align, is_volatile);
84828311
8483 if (safety and module.comp.bin_file.options.valgrind) {
8312 if (safety and mod.comp.bin_file.options.valgrind) {
84848313 self.valgrindMarkUndef(dest_ptr, len);
84858314 }
84868315 return null;
......@@ -8490,8 +8319,7 @@ pub const FuncGen = struct {
84908319 // repeating byte pattern, for example, `@as(u64, 0)` has a
84918320 // repeating byte pattern of 0 bytes. In such case, the memset
84928321 // intrinsic can be used.
8493 var value_buffer: Value.Payload.U64 = undefined;
8494 if (try elem_val.hasRepeatedByteRepr(elem_ty, module, &value_buffer)) |byte_val| {
8322 if (try elem_val.hasRepeatedByteRepr(elem_ty, mod)) |byte_val| {
84958323 const fill_byte = try self.resolveValue(.{
84968324 .ty = Type.u8,
84978325 .val = byte_val,
......@@ -8503,7 +8331,7 @@ pub const FuncGen = struct {
85038331 }
85048332
85058333 const value = try self.resolveInst(bin_op.rhs);
8506 const elem_abi_size = elem_ty.abiSize(target);
8334 const elem_abi_size = elem_ty.abiSize(mod);
85078335
85088336 if (elem_abi_size == 1) {
85098337 // In this case we can take advantage of LLVM's intrinsic.
......@@ -8535,9 +8363,9 @@ pub const FuncGen = struct {
85358363 const end_block = self.context.appendBasicBlock(self.llvm_func, "InlineMemsetEnd");
85368364
85378365 const llvm_usize_ty = self.context.intType(target.ptrBitWidth());
8538 const len = switch (ptr_ty.ptrSize()) {
8366 const len = switch (ptr_ty.ptrSize(mod)) {
85398367 .Slice => self.builder.buildExtractValue(dest_slice, 1, ""),
8540 .One => llvm_usize_ty.constInt(ptr_ty.childType().arrayLen(), .False),
8368 .One => llvm_usize_ty.constInt(ptr_ty.childType(mod).arrayLen(mod), .False),
85418369 .Many, .C => unreachable,
85428370 };
85438371 const elem_llvm_ty = try self.dg.lowerType(elem_ty);
......@@ -8551,9 +8379,9 @@ pub const FuncGen = struct {
85518379 _ = self.builder.buildCondBr(end, body_block, end_block);
85528380
85538381 self.builder.positionBuilderAtEnd(body_block);
8554 const elem_abi_alignment = elem_ty.abiAlignment(target);
8382 const elem_abi_alignment = elem_ty.abiAlignment(mod);
85558383 const it_ptr_alignment = @min(elem_abi_alignment, dest_ptr_align);
8556 if (isByRef(elem_ty)) {
8384 if (isByRef(elem_ty, mod)) {
85578385 _ = self.builder.buildMemCpy(
85588386 it_ptr,
85598387 it_ptr_alignment,
......@@ -8583,19 +8411,19 @@ pub const FuncGen = struct {
85838411 fn airMemcpy(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
85848412 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
85858413 const dest_slice = try self.resolveInst(bin_op.lhs);
8586 const dest_ptr_ty = self.air.typeOf(bin_op.lhs);
8414 const dest_ptr_ty = self.typeOf(bin_op.lhs);
85878415 const src_slice = try self.resolveInst(bin_op.rhs);
8588 const src_ptr_ty = self.air.typeOf(bin_op.rhs);
8416 const src_ptr_ty = self.typeOf(bin_op.rhs);
85898417 const src_ptr = self.sliceOrArrayPtr(src_slice, src_ptr_ty);
85908418 const len = self.sliceOrArrayLenInBytes(dest_slice, dest_ptr_ty);
85918419 const dest_ptr = self.sliceOrArrayPtr(dest_slice, dest_ptr_ty);
8592 const is_volatile = src_ptr_ty.isVolatilePtr() or dest_ptr_ty.isVolatilePtr();
8593 const target = self.dg.module.getTarget();
8420 const mod = self.dg.module;
8421 const is_volatile = src_ptr_ty.isVolatilePtr(mod) or dest_ptr_ty.isVolatilePtr(mod);
85948422 _ = self.builder.buildMemCpy(
85958423 dest_ptr,
8596 dest_ptr_ty.ptrAlignment(target),
8424 dest_ptr_ty.ptrAlignment(mod),
85978425 src_ptr,
8598 src_ptr_ty.ptrAlignment(target),
8426 src_ptr_ty.ptrAlignment(mod),
85998427 len,
86008428 is_volatile,
86018429 );
......@@ -8603,10 +8431,10 @@ pub const FuncGen = struct {
86038431 }
86048432
86058433 fn airSetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8434 const mod = self.dg.module;
86068435 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8607 const un_ty = self.air.typeOf(bin_op.lhs).childType();
8608 const target = self.dg.module.getTarget();
8609 const layout = un_ty.unionGetLayout(target);
8436 const un_ty = self.typeOf(bin_op.lhs).childType(mod);
8437 const layout = un_ty.unionGetLayout(mod);
86108438 if (layout.tag_size == 0) return null;
86118439 const union_ptr = try self.resolveInst(bin_op.lhs);
86128440 const new_tag = try self.resolveInst(bin_op.rhs);
......@@ -8624,13 +8452,13 @@ pub const FuncGen = struct {
86248452 }
86258453
86268454 fn airGetUnionTag(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8455 const mod = self.dg.module;
86278456 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8628 const un_ty = self.air.typeOf(ty_op.operand);
8629 const target = self.dg.module.getTarget();
8630 const layout = un_ty.unionGetLayout(target);
8457 const un_ty = self.typeOf(ty_op.operand);
8458 const layout = un_ty.unionGetLayout(mod);
86318459 if (layout.tag_size == 0) return null;
86328460 const union_handle = try self.resolveInst(ty_op.operand);
8633 if (isByRef(un_ty)) {
8461 if (isByRef(un_ty, mod)) {
86348462 const llvm_un_ty = try self.dg.lowerType(un_ty);
86358463 if (layout.payload_size == 0) {
86368464 return self.builder.buildLoad(llvm_un_ty, union_handle, "");
......@@ -8650,7 +8478,7 @@ pub const FuncGen = struct {
86508478 fn airUnaryOp(self: *FuncGen, inst: Air.Inst.Index, comptime op: FloatOp) !?*llvm.Value {
86518479 const un_op = self.air.instructions.items(.data)[inst].un_op;
86528480 const operand = try self.resolveInst(un_op);
8653 const operand_ty = self.air.typeOf(un_op);
8481 const operand_ty = self.typeOf(un_op);
86548482
86558483 return self.buildFloatOp(op, operand_ty, 1, .{operand});
86568484 }
......@@ -8660,14 +8488,15 @@ pub const FuncGen = struct {
86608488
86618489 const un_op = self.air.instructions.items(.data)[inst].un_op;
86628490 const operand = try self.resolveInst(un_op);
8663 const operand_ty = self.air.typeOf(un_op);
8491 const operand_ty = self.typeOf(un_op);
86648492
86658493 return self.buildFloatOp(.neg, operand_ty, 1, .{operand});
86668494 }
86678495
86688496 fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8497 const mod = self.dg.module;
86698498 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8670 const operand_ty = self.air.typeOf(ty_op.operand);
8499 const operand_ty = self.typeOf(ty_op.operand);
86718500 const operand = try self.resolveInst(ty_op.operand);
86728501
86738502 const llvm_i1 = self.context.intType(1);
......@@ -8676,12 +8505,11 @@ pub const FuncGen = struct {
86768505
86778506 const params = [_]*llvm.Value{ operand, llvm_i1.constNull() };
86788507 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
8679 const result_ty = self.air.typeOfIndex(inst);
8508 const result_ty = self.typeOfIndex(inst);
86808509 const result_llvm_ty = try self.dg.lowerType(result_ty);
86818510
8682 const target = self.dg.module.getTarget();
8683 const bits = operand_ty.intInfo(target).bits;
8684 const result_bits = result_ty.intInfo(target).bits;
8511 const bits = operand_ty.intInfo(mod).bits;
8512 const result_bits = result_ty.intInfo(mod).bits;
86858513 if (bits > result_bits) {
86868514 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
86878515 } else if (bits < result_bits) {
......@@ -8692,8 +8520,9 @@ pub const FuncGen = struct {
86928520 }
86938521
86948522 fn airBitOp(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8523 const mod = self.dg.module;
86958524 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8696 const operand_ty = self.air.typeOf(ty_op.operand);
8525 const operand_ty = self.typeOf(ty_op.operand);
86978526 const operand = try self.resolveInst(ty_op.operand);
86988527
86998528 const params = [_]*llvm.Value{operand};
......@@ -8701,12 +8530,11 @@ pub const FuncGen = struct {
87018530 const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty});
87028531
87038532 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
8704 const result_ty = self.air.typeOfIndex(inst);
8533 const result_ty = self.typeOfIndex(inst);
87058534 const result_llvm_ty = try self.dg.lowerType(result_ty);
87068535
8707 const target = self.dg.module.getTarget();
8708 const bits = operand_ty.intInfo(target).bits;
8709 const result_bits = result_ty.intInfo(target).bits;
8536 const bits = operand_ty.intInfo(mod).bits;
8537 const result_bits = result_ty.intInfo(mod).bits;
87108538 if (bits > result_bits) {
87118539 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
87128540 } else if (bits < result_bits) {
......@@ -8717,10 +8545,10 @@ pub const FuncGen = struct {
87178545 }
87188546
87198547 fn airByteSwap(self: *FuncGen, inst: Air.Inst.Index, llvm_fn_name: []const u8) !?*llvm.Value {
8720 const target = self.dg.module.getTarget();
8548 const mod = self.dg.module;
87218549 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
8722 const operand_ty = self.air.typeOf(ty_op.operand);
8723 var bits = operand_ty.intInfo(target).bits;
8550 const operand_ty = self.typeOf(ty_op.operand);
8551 var bits = operand_ty.intInfo(mod).bits;
87248552 assert(bits % 8 == 0);
87258553
87268554 var operand = try self.resolveInst(ty_op.operand);
......@@ -8730,8 +8558,8 @@ pub const FuncGen = struct {
87308558 // If not an even byte-multiple, we need zero-extend + shift-left 1 byte
87318559 // The truncated result at the end will be the correct bswap
87328560 const scalar_llvm_ty = self.context.intType(bits + 8);
8733 if (operand_ty.zigTypeTag() == .Vector) {
8734 const vec_len = operand_ty.vectorLen();
8561 if (operand_ty.zigTypeTag(mod) == .Vector) {
8562 const vec_len = operand_ty.vectorLen(mod);
87358563 operand_llvm_ty = scalar_llvm_ty.vectorType(vec_len);
87368564
87378565 const shifts = try self.gpa.alloc(*llvm.Value, vec_len);
......@@ -8757,9 +8585,9 @@ pub const FuncGen = struct {
87578585
87588586 const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, &params, params.len, .C, .Auto, "");
87598587
8760 const result_ty = self.air.typeOfIndex(inst);
8588 const result_ty = self.typeOfIndex(inst);
87618589 const result_llvm_ty = try self.dg.lowerType(result_ty);
8762 const result_bits = result_ty.intInfo(target).bits;
8590 const result_bits = result_ty.intInfo(mod).bits;
87638591 if (bits > result_bits) {
87648592 return self.builder.buildTrunc(wrong_size_result, result_llvm_ty, "");
87658593 } else if (bits < result_bits) {
......@@ -8770,28 +8598,23 @@ pub const FuncGen = struct {
87708598 }
87718599
87728600 fn airErrorSetHasValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8601 const mod = self.dg.module;
87738602 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
87748603 const operand = try self.resolveInst(ty_op.operand);
87758604 const error_set_ty = self.air.getRefType(ty_op.ty);
87768605
8777 const names = error_set_ty.errorSetNames();
8606 const names = error_set_ty.errorSetNames(mod);
87788607 const valid_block = self.context.appendBasicBlock(self.llvm_func, "Valid");
87798608 const invalid_block = self.context.appendBasicBlock(self.llvm_func, "Invalid");
87808609 const end_block = self.context.appendBasicBlock(self.llvm_func, "End");
87818610 const switch_instr = self.builder.buildSwitch(operand, invalid_block, @intCast(c_uint, names.len));
87828611
87838612 for (names) |name| {
8784 const err_int = self.dg.module.global_error_set.get(name).?;
8785 const this_tag_int_value = int: {
8786 var tag_val_payload: Value.Payload.U64 = .{
8787 .base = .{ .tag = .int_u64 },
8788 .data = err_int,
8789 };
8790 break :int try self.dg.lowerValue(.{
8791 .ty = Type.err_int,
8792 .val = Value.initPayload(&tag_val_payload.base),
8793 });
8794 };
8613 const err_int = @intCast(Module.ErrorInt, mod.global_error_set.getIndex(name).?);
8614 const this_tag_int_value = try self.dg.lowerValue(.{
8615 .ty = Type.err_int,
8616 .val = try mod.intValue(Type.err_int, err_int),
8617 });
87958618 switch_instr.addCase(this_tag_int_value, valid_block);
87968619 }
87978620 self.builder.positionBuilderAtEnd(valid_block);
......@@ -8817,7 +8640,7 @@ pub const FuncGen = struct {
88178640 fn airIsNamedEnumValue(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
88188641 const un_op = self.air.instructions.items(.data)[inst].un_op;
88198642 const operand = try self.resolveInst(un_op);
8820 const enum_ty = self.air.typeOf(un_op);
8643 const enum_ty = self.typeOf(un_op);
88218644
88228645 const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty);
88238646 const params = [_]*llvm.Value{operand};
......@@ -8825,25 +8648,22 @@ pub const FuncGen = struct {
88258648 }
88268649
88278650 fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !*llvm.Value {
8828 const enum_decl = enum_ty.getOwnerDecl();
8651 const mod = self.dg.module;
8652 const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
88298653
88308654 // TODO: detect when the type changes and re-emit this function.
8831 const gop = try self.dg.object.named_enum_map.getOrPut(self.dg.gpa, enum_decl);
8655 const gop = try self.dg.object.named_enum_map.getOrPut(self.dg.gpa, enum_type.decl);
88328656 if (gop.found_existing) return gop.value_ptr.*;
8833 errdefer assert(self.dg.object.named_enum_map.remove(enum_decl));
8657 errdefer assert(self.dg.object.named_enum_map.remove(enum_type.decl));
88348658
88358659 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
88368660 defer arena_allocator.deinit();
88378661 const arena = arena_allocator.allocator();
88388662
8839 const mod = self.dg.module;
8840 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8841 defer self.gpa.free(fqn);
8842 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn});
8663 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
8664 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{}", .{fqn.fmt(&mod.intern_pool)});
88438665
8844 var int_tag_type_buffer: Type.Payload.Bits = undefined;
8845 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
8846 const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)};
8666 const param_types = [_]*llvm.Type{try self.dg.lowerType(enum_type.tag_ty.toType())};
88478667
88488668 const llvm_ret_ty = try self.dg.lowerType(Type.bool);
88498669 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);
......@@ -8866,21 +8686,17 @@ pub const FuncGen = struct {
88668686 self.builder.positionBuilderAtEnd(entry_block);
88678687 self.builder.clearCurrentDebugLocation();
88688688
8869 const fields = enum_ty.enumFields();
88708689 const named_block = self.context.appendBasicBlock(fn_val, "Named");
88718690 const unnamed_block = self.context.appendBasicBlock(fn_val, "Unnamed");
88728691 const tag_int_value = fn_val.getParam(0);
8873 const switch_instr = self.builder.buildSwitch(tag_int_value, unnamed_block, @intCast(c_uint, fields.count()));
8692 const switch_instr = self.builder.buildSwitch(tag_int_value, unnamed_block, @intCast(c_uint, enum_type.names.len));
88748693
8875 for (fields.keys(), 0..) |_, field_index| {
8694 for (enum_type.names, 0..) |_, field_index_usize| {
8695 const field_index = @intCast(u32, field_index_usize);
88768696 const this_tag_int_value = int: {
8877 var tag_val_payload: Value.Payload.U32 = .{
8878 .base = .{ .tag = .enum_field_index },
8879 .data = @intCast(u32, field_index),
8880 };
88818697 break :int try self.dg.lowerValue(.{
88828698 .ty = enum_ty,
8883 .val = Value.initPayload(&tag_val_payload.base),
8699 .val = try mod.enumValueFieldIndex(enum_ty, field_index),
88848700 });
88858701 };
88868702 switch_instr.addCase(this_tag_int_value, named_block);
......@@ -8896,7 +8712,7 @@ pub const FuncGen = struct {
88968712 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
88978713 const un_op = self.air.instructions.items(.data)[inst].un_op;
88988714 const operand = try self.resolveInst(un_op);
8899 const enum_ty = self.air.typeOf(un_op);
8715 const enum_ty = self.typeOf(un_op);
89008716
89018717 const llvm_fn = try self.getEnumTagNameFunction(enum_ty);
89028718 const params = [_]*llvm.Value{operand};
......@@ -8904,31 +8720,27 @@ pub const FuncGen = struct {
89048720 }
89058721
89068722 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*llvm.Value {
8907 const enum_decl = enum_ty.getOwnerDecl();
8723 const mod = self.dg.module;
8724 const enum_type = mod.intern_pool.indexToKey(enum_ty.toIntern()).enum_type;
89088725
89098726 // TODO: detect when the type changes and re-emit this function.
8910 const gop = try self.dg.object.decl_map.getOrPut(self.dg.gpa, enum_decl);
8727 const gop = try self.dg.object.decl_map.getOrPut(self.dg.gpa, enum_type.decl);
89118728 if (gop.found_existing) return gop.value_ptr.*;
8912 errdefer assert(self.dg.object.decl_map.remove(enum_decl));
8729 errdefer assert(self.dg.object.decl_map.remove(enum_type.decl));
89138730
89148731 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
89158732 defer arena_allocator.deinit();
89168733 const arena = arena_allocator.allocator();
89178734
8918 const mod = self.dg.module;
8919 const fqn = try mod.declPtr(enum_decl).getFullyQualifiedName(mod);
8920 defer self.gpa.free(fqn);
8921 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{fqn});
8735 const fqn = try mod.declPtr(enum_type.decl).getFullyQualifiedName(mod);
8736 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{fqn.fmt(&mod.intern_pool)});
89228737
8923 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
8738 const slice_ty = Type.slice_const_u8_sentinel_0;
89248739 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
89258740 const usize_llvm_ty = try self.dg.lowerType(Type.usize);
8926 const target = self.dg.module.getTarget();
8927 const slice_alignment = slice_ty.abiAlignment(target);
8741 const slice_alignment = slice_ty.abiAlignment(mod);
89288742
8929 var int_tag_type_buffer: Type.Payload.Bits = undefined;
8930 const int_tag_ty = enum_ty.intTagType(&int_tag_type_buffer);
8931 const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)};
8743 const param_types = [_]*llvm.Type{try self.dg.lowerType(enum_type.tag_ty.toType())};
89328744
89338745 const fn_type = llvm.functionType(llvm_ret_ty, &param_types, param_types.len, .False);
89348746 const fn_val = self.dg.object.llvm_module.addFunction(llvm_fn_name, fn_type);
......@@ -8950,16 +8762,17 @@ pub const FuncGen = struct {
89508762 self.builder.positionBuilderAtEnd(entry_block);
89518763 self.builder.clearCurrentDebugLocation();
89528764
8953 const fields = enum_ty.enumFields();
89548765 const bad_value_block = self.context.appendBasicBlock(fn_val, "BadValue");
89558766 const tag_int_value = fn_val.getParam(0);
8956 const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @intCast(c_uint, fields.count()));
8767 const switch_instr = self.builder.buildSwitch(tag_int_value, bad_value_block, @intCast(c_uint, enum_type.names.len));
89578768
89588769 const array_ptr_indices = [_]*llvm.Value{
89598770 usize_llvm_ty.constNull(), usize_llvm_ty.constNull(),
89608771 };
89618772
8962 for (fields.keys(), 0..) |name, field_index| {
8773 for (enum_type.names, 0..) |name_ip, field_index_usize| {
8774 const field_index = @intCast(u32, field_index_usize);
8775 const name = mod.intern_pool.stringToSlice(name_ip);
89638776 const str_init = self.context.constString(name.ptr, @intCast(c_uint, name.len), .False);
89648777 const str_init_llvm_ty = str_init.typeOf();
89658778 const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, "");
......@@ -8982,16 +8795,10 @@ pub const FuncGen = struct {
89828795 slice_global.setAlignment(slice_alignment);
89838796
89848797 const return_block = self.context.appendBasicBlock(fn_val, "Name");
8985 const this_tag_int_value = int: {
8986 var tag_val_payload: Value.Payload.U32 = .{
8987 .base = .{ .tag = .enum_field_index },
8988 .data = @intCast(u32, field_index),
8989 };
8990 break :int try self.dg.lowerValue(.{
8991 .ty = enum_ty,
8992 .val = Value.initPayload(&tag_val_payload.base),
8993 });
8994 };
8798 const this_tag_int_value = try self.dg.lowerValue(.{
8799 .ty = enum_ty,
8800 .val = try mod.enumValueFieldIndex(enum_ty, field_index),
8801 });
89958802 switch_instr.addCase(this_tag_int_value, return_block);
89968803
89978804 self.builder.positionBuilderAtEnd(return_block);
......@@ -9027,7 +8834,7 @@ pub const FuncGen = struct {
90278834 fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
90288835 const un_op = self.air.instructions.items(.data)[inst].un_op;
90298836 const operand = try self.resolveInst(un_op);
9030 const slice_ty = self.air.typeOfIndex(inst);
8837 const slice_ty = self.typeOfIndex(inst);
90318838 const slice_llvm_ty = try self.dg.lowerType(slice_ty);
90328839
90338840 const error_name_table_ptr = try self.getErrorNameTable();
......@@ -9039,10 +8846,11 @@ pub const FuncGen = struct {
90398846 }
90408847
90418848 fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8849 const mod = self.dg.module;
90428850 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
90438851 const scalar = try self.resolveInst(ty_op.operand);
9044 const vector_ty = self.air.typeOfIndex(inst);
9045 const len = vector_ty.vectorLen();
8852 const vector_ty = self.typeOfIndex(inst);
8853 const len = vector_ty.vectorLen(mod);
90468854 return self.builder.buildVectorSplat(len, scalar, "");
90478855 }
90488856
......@@ -9057,13 +8865,14 @@ pub const FuncGen = struct {
90578865 }
90588866
90598867 fn airShuffle(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
8868 const mod = self.dg.module;
90608869 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
90618870 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
90628871 const a = try self.resolveInst(extra.a);
90638872 const b = try self.resolveInst(extra.b);
9064 const mask = self.air.values[extra.mask];
8873 const mask = extra.mask.toValue();
90658874 const mask_len = extra.mask_len;
9066 const a_len = self.air.typeOf(extra.a).vectorLen();
8875 const a_len = self.typeOf(extra.a).vectorLen(mod);
90678876
90688877 // LLVM uses integers larger than the length of the first array to
90698878 // index into the second array. This was deemed unnecessarily fragile
......@@ -9076,12 +8885,11 @@ pub const FuncGen = struct {
90768885 const llvm_i32 = self.context.intType(32);
90778886
90788887 for (values, 0..) |*val, i| {
9079 var buf: Value.ElemValueBuffer = undefined;
9080 const elem = mask.elemValueBuffer(self.dg.module, i, &buf);
9081 if (elem.isUndef()) {
8888 const elem = try mask.elemValue(mod, i);
8889 if (elem.isUndef(mod)) {
90828890 val.* = llvm_i32.getUndef();
90838891 } else {
9084 const int = elem.toSignedInt(self.dg.module.getTarget());
8892 const int = elem.toSignedInt(mod);
90858893 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
90868894 val.* = llvm_i32.constInt(unsigned, .False);
90878895 }
......@@ -9157,32 +8965,33 @@ pub const FuncGen = struct {
91578965
91588966 fn airReduce(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*llvm.Value {
91598967 self.builder.setFastMath(want_fast_math);
9160 const target = self.dg.module.getTarget();
8968 const mod = self.dg.module;
8969 const target = mod.getTarget();
91618970
91628971 const reduce = self.air.instructions.items(.data)[inst].reduce;
91638972 const operand = try self.resolveInst(reduce.operand);
9164 const operand_ty = self.air.typeOf(reduce.operand);
9165 const scalar_ty = self.air.typeOfIndex(inst);
8973 const operand_ty = self.typeOf(reduce.operand);
8974 const scalar_ty = self.typeOfIndex(inst);
91668975
91678976 switch (reduce.operation) {
91688977 .And => return self.builder.buildAndReduce(operand),
91698978 .Or => return self.builder.buildOrReduce(operand),
91708979 .Xor => return self.builder.buildXorReduce(operand),
9171 .Min => switch (scalar_ty.zigTypeTag()) {
9172 .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt()),
8980 .Min => switch (scalar_ty.zigTypeTag(mod)) {
8981 .Int => return self.builder.buildIntMinReduce(operand, scalar_ty.isSignedInt(mod)),
91738982 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
91748983 return self.builder.buildFPMinReduce(operand);
91758984 },
91768985 else => unreachable,
91778986 },
9178 .Max => switch (scalar_ty.zigTypeTag()) {
9179 .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt()),
8987 .Max => switch (scalar_ty.zigTypeTag(mod)) {
8988 .Int => return self.builder.buildIntMaxReduce(operand, scalar_ty.isSignedInt(mod)),
91808989 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
91818990 return self.builder.buildFPMaxReduce(operand);
91828991 },
91838992 else => unreachable,
91848993 },
9185 .Add => switch (scalar_ty.zigTypeTag()) {
8994 .Add => switch (scalar_ty.zigTypeTag(mod)) {
91868995 .Int => return self.builder.buildAddReduce(operand),
91878996 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
91888997 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
......@@ -9191,7 +9000,7 @@ pub const FuncGen = struct {
91919000 },
91929001 else => unreachable,
91939002 },
9194 .Mul => switch (scalar_ty.zigTypeTag()) {
9003 .Mul => switch (scalar_ty.zigTypeTag(mod)) {
91959004 .Int => return self.builder.buildMulReduce(operand),
91969005 .Float => if (intrinsicsAllowed(scalar_ty, target)) {
91979006 const scalar_llvm_ty = try self.dg.lowerType(scalar_ty);
......@@ -9221,35 +9030,32 @@ pub const FuncGen = struct {
92219030 }) catch unreachable,
92229031 else => unreachable,
92239032 };
9224 var init_value_payload = Value.Payload.Float_32{
9225 .data = switch (reduce.operation) {
9226 .Min => std.math.nan(f32),
9227 .Max => std.math.nan(f32),
9228 .Add => -0.0,
9229 .Mul => 1.0,
9230 else => unreachable,
9231 },
9232 };
92339033
92349034 const param_llvm_ty = try self.dg.lowerType(scalar_ty);
92359035 const param_types = [2]*llvm.Type{ param_llvm_ty, param_llvm_ty };
92369036 const libc_fn = self.getLibcFunction(fn_name, &param_types, param_llvm_ty);
92379037 const init_value = try self.dg.lowerValue(.{
92389038 .ty = scalar_ty,
9239 .val = Value.initPayload(&init_value_payload.base),
9039 .val = try mod.floatValue(scalar_ty, switch (reduce.operation) {
9040 .Min => std.math.nan(f32),
9041 .Max => std.math.nan(f32),
9042 .Add => -0.0,
9043 .Mul => 1.0,
9044 else => unreachable,
9045 }),
92409046 });
9241 return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(), init_value);
9047 return self.buildReducedCall(libc_fn, operand, operand_ty.vectorLen(mod), init_value);
92429048 }
92439049
92449050 fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9051 const mod = self.dg.module;
92459052 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9246 const result_ty = self.air.typeOfIndex(inst);
9247 const len = @intCast(usize, result_ty.arrayLen());
9053 const result_ty = self.typeOfIndex(inst);
9054 const len = @intCast(usize, result_ty.arrayLen(mod));
92489055 const elements = @ptrCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]);
92499056 const llvm_result_ty = try self.dg.lowerType(result_ty);
9250 const target = self.dg.module.getTarget();
92519057
9252 switch (result_ty.zigTypeTag()) {
9058 switch (result_ty.zigTypeTag(mod)) {
92539059 .Vector => {
92549060 const llvm_u32 = self.context.intType(32);
92559061
......@@ -9262,10 +9068,10 @@ pub const FuncGen = struct {
92629068 return vector;
92639069 },
92649070 .Struct => {
9265 if (result_ty.containerLayout() == .Packed) {
9266 const struct_obj = result_ty.castTag(.@"struct").?.data;
9071 if (result_ty.containerLayout(mod) == .Packed) {
9072 const struct_obj = mod.typeToStruct(result_ty).?;
92679073 assert(struct_obj.haveLayout());
9268 const big_bits = struct_obj.backing_int_ty.bitSize(target);
9074 const big_bits = struct_obj.backing_int_ty.bitSize(mod);
92699075 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));
92709076 const fields = struct_obj.fields.values();
92719077 comptime assert(Type.packed_struct_layout_version == 2);
......@@ -9273,12 +9079,12 @@ pub const FuncGen = struct {
92739079 var running_bits: u16 = 0;
92749080 for (elements, 0..) |elem, i| {
92759081 const field = fields[i];
9276 if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
9082 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
92779083
92789084 const non_int_val = try self.resolveInst(elem);
9279 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
9085 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
92809086 const small_int_ty = self.context.intType(ty_bit_size);
9281 const small_int_val = if (field.ty.isPtrAtRuntime())
9087 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
92829088 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
92839089 else
92849090 self.builder.buildBitCast(non_int_val, small_int_ty, "");
......@@ -9294,30 +9100,28 @@ pub const FuncGen = struct {
92949100 return running_int;
92959101 }
92969102
9297 var ptr_ty_buf: Type.Payload.Pointer = undefined;
9298
9299 if (isByRef(result_ty)) {
9103 if (isByRef(result_ty, mod)) {
93009104 const llvm_u32 = self.context.intType(32);
93019105 // TODO in debug builds init to undef so that the padding will be 0xaa
93029106 // even if we fully populate the fields.
9303 const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(target));
9107 const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod));
93049108
93059109 var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined };
93069110 for (elements, 0..) |elem, i| {
9307 if (result_ty.structFieldValueComptime(i) != null) continue;
9111 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93089112
93099113 const llvm_elem = try self.resolveInst(elem);
9310 const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?;
9114 const llvm_i = llvmField(result_ty, i, mod).?.index;
93119115 indices[1] = llvm_u32.constInt(llvm_i, .False);
93129116 const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, "");
9313 var field_ptr_payload: Type.Payload.Pointer = .{
9314 .data = .{
9315 .pointee_type = self.air.typeOf(elem),
9316 .@"align" = result_ty.structFieldAlign(i, target),
9317 .@"addrspace" = .generic,
9117 const field_ptr_ty = try mod.ptrType(.{
9118 .child = self.typeOf(elem).toIntern(),
9119 .flags = .{
9120 .alignment = InternPool.Alignment.fromNonzeroByteUnits(
9121 result_ty.structFieldAlign(i, mod),
9122 ),
93189123 },
9319 };
9320 const field_ptr_ty = Type.initPayload(&field_ptr_payload.base);
9124 });
93219125 try self.store(field_ptr, field_ptr_ty, llvm_elem, .NotAtomic);
93229126 }
93239127
......@@ -9325,29 +9129,25 @@ pub const FuncGen = struct {
93259129 } else {
93269130 var result = llvm_result_ty.getUndef();
93279131 for (elements, 0..) |elem, i| {
9328 if (result_ty.structFieldValueComptime(i) != null) continue;
9132 if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
93299133
93309134 const llvm_elem = try self.resolveInst(elem);
9331 const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?;
9135 const llvm_i = llvmField(result_ty, i, mod).?.index;
93329136 result = self.builder.buildInsertValue(result, llvm_elem, llvm_i, "");
93339137 }
93349138 return result;
93359139 }
93369140 },
93379141 .Array => {
9338 assert(isByRef(result_ty));
9142 assert(isByRef(result_ty, mod));
93399143
93409144 const llvm_usize = try self.dg.lowerType(Type.usize);
9341 const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(target));
9145 const alloca_inst = self.buildAlloca(llvm_result_ty, result_ty.abiAlignment(mod));
93429146
9343 const array_info = result_ty.arrayInfo();
9344 var elem_ptr_payload: Type.Payload.Pointer = .{
9345 .data = .{
9346 .pointee_type = array_info.elem_type,
9347 .@"addrspace" = .generic,
9348 },
9349 };
9350 const elem_ptr_ty = Type.initPayload(&elem_ptr_payload.base);
9147 const array_info = result_ty.arrayInfo(mod);
9148 const elem_ptr_ty = try mod.ptrType(.{
9149 .child = array_info.elem_type.toIntern(),
9150 });
93519151
93529152 for (elements, 0..) |elem, i| {
93539153 const indices: [2]*llvm.Value = .{
......@@ -9379,22 +9179,22 @@ pub const FuncGen = struct {
93799179 }
93809180
93819181 fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
9182 const mod = self.dg.module;
93829183 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
93839184 const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data;
9384 const union_ty = self.air.typeOfIndex(inst);
9185 const union_ty = self.typeOfIndex(inst);
93859186 const union_llvm_ty = try self.dg.lowerType(union_ty);
9386 const target = self.dg.module.getTarget();
9387 const layout = union_ty.unionGetLayout(target);
9388 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
9187 const layout = union_ty.unionGetLayout(mod);
9188 const union_obj = mod.typeToUnion(union_ty).?;
93899189
93909190 if (union_obj.layout == .Packed) {
9391 const big_bits = union_ty.bitSize(target);
9191 const big_bits = union_ty.bitSize(mod);
93929192 const int_llvm_ty = self.context.intType(@intCast(c_uint, big_bits));
93939193 const field = union_obj.fields.values()[extra.field_index];
93949194 const non_int_val = try self.resolveInst(extra.init);
9395 const ty_bit_size = @intCast(u16, field.ty.bitSize(target));
9195 const ty_bit_size = @intCast(u16, field.ty.bitSize(mod));
93969196 const small_int_ty = self.context.intType(ty_bit_size);
9397 const small_int_val = if (field.ty.isPtrAtRuntime())
9197 const small_int_val = if (field.ty.isPtrAtRuntime(mod))
93989198 self.builder.buildPtrToInt(non_int_val, small_int_ty, "")
93999199 else
94009200 self.builder.buildBitCast(non_int_val, small_int_ty, "");
......@@ -9402,26 +9202,21 @@ pub const FuncGen = struct {
94029202 }
94039203
94049204 const tag_int = blk: {
9405 const tag_ty = union_ty.unionTagTypeHypothetical();
9205 const tag_ty = union_ty.unionTagTypeHypothetical(mod);
94069206 const union_field_name = union_obj.fields.keys()[extra.field_index];
9407 const enum_field_index = tag_ty.enumFieldIndex(union_field_name).?;
9408 var tag_val_payload: Value.Payload.U32 = .{
9409 .base = .{ .tag = .enum_field_index },
9410 .data = @intCast(u32, enum_field_index),
9411 };
9412 const tag_val = Value.initPayload(&tag_val_payload.base);
9413 var int_payload: Value.Payload.U64 = undefined;
9414 const tag_int_val = tag_val.enumToInt(tag_ty, &int_payload);
9415 break :blk tag_int_val.toUnsignedInt(target);
9207 const enum_field_index = tag_ty.enumFieldIndex(union_field_name, mod).?;
9208 const tag_val = try mod.enumValueFieldIndex(tag_ty, enum_field_index);
9209 const tag_int_val = try tag_val.enumToInt(tag_ty, mod);
9210 break :blk tag_int_val.toUnsignedInt(mod);
94169211 };
94179212 if (layout.payload_size == 0) {
94189213 if (layout.tag_size == 0) {
94199214 return null;
94209215 }
9421 assert(!isByRef(union_ty));
9216 assert(!isByRef(union_ty, mod));
94229217 return union_llvm_ty.constInt(tag_int, .False);
94239218 }
9424 assert(isByRef(union_ty));
9219 assert(isByRef(union_ty, mod));
94259220 // The llvm type of the alloca will be the named LLVM union type, and will not
94269221 // necessarily match the format that we need, depending on which tag is active.
94279222 // We must construct the correct unnamed struct type here, in order to then set
......@@ -9431,12 +9226,12 @@ pub const FuncGen = struct {
94319226 assert(union_obj.haveFieldTypes());
94329227 const field = union_obj.fields.values()[extra.field_index];
94339228 const field_llvm_ty = try self.dg.lowerType(field.ty);
9434 const field_size = field.ty.abiSize(target);
9435 const field_align = field.normalAlignment(target);
9229 const field_size = field.ty.abiSize(mod);
9230 const field_align = field.normalAlignment(mod);
94369231
94379232 const llvm_union_ty = t: {
94389233 const payload = p: {
9439 if (!field.ty.hasRuntimeBitsIgnoreComptime()) {
9234 if (!field.ty.hasRuntimeBitsIgnoreComptime(mod)) {
94409235 const padding_len = @intCast(c_uint, layout.payload_size);
94419236 break :p self.context.intType(8).arrayType(padding_len);
94429237 }
......@@ -9472,14 +9267,12 @@ pub const FuncGen = struct {
94729267 // tag and the payload.
94739268 const index_type = self.context.intType(32);
94749269
9475 var field_ptr_payload: Type.Payload.Pointer = .{
9476 .data = .{
9477 .pointee_type = field.ty,
9478 .@"align" = field_align,
9479 .@"addrspace" = .generic,
9270 const field_ptr_ty = try mod.ptrType(.{
9271 .child = field.ty.toIntern(),
9272 .flags = .{
9273 .alignment = InternPool.Alignment.fromNonzeroByteUnits(field_align),
94809274 },
9481 };
9482 const field_ptr_ty = Type.initPayload(&field_ptr_payload.base);
9275 });
94839276 if (layout.tag_size == 0) {
94849277 const indices: [3]*llvm.Value = .{
94859278 index_type.constNull(),
......@@ -9511,7 +9304,7 @@ pub const FuncGen = struct {
95119304 const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty);
95129305 const llvm_tag = tag_llvm_ty.constInt(tag_int, .False);
95139306 const store_inst = self.builder.buildStore(llvm_tag, field_ptr);
9514 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target));
9307 store_inst.setAlignment(union_obj.tag_ty.abiAlignment(mod));
95159308 }
95169309
95179310 return result_ptr;
......@@ -9535,7 +9328,8 @@ pub const FuncGen = struct {
95359328 // by the target.
95369329 // To work around this, don't emit llvm.prefetch in this case.
95379330 // See https://bugs.llvm.org/show_bug.cgi?id=21037
9538 const target = self.dg.module.getTarget();
9331 const mod = self.dg.module;
9332 const target = mod.getTarget();
95399333 switch (prefetch.cache) {
95409334 .instruction => switch (target.cpu.arch) {
95419335 .x86_64,
......@@ -9584,7 +9378,7 @@ pub const FuncGen = struct {
95849378
95859379 fn airAddrSpaceCast(self: *FuncGen, inst: Air.Inst.Index) !?*llvm.Value {
95869380 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
9587 const inst_ty = self.air.typeOfIndex(inst);
9381 const inst_ty = self.typeOfIndex(inst);
95889382 const operand = try self.resolveInst(ty_op.operand);
95899383
95909384 const llvm_dest_ty = try self.dg.lowerType(inst_ty);
......@@ -9658,8 +9452,9 @@ pub const FuncGen = struct {
96589452 return table;
96599453 }
96609454
9661 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
9662 const slice_alignment = slice_ty.abiAlignment(self.dg.module.getTarget());
9455 const mod = self.dg.module;
9456 const slice_ty = Type.slice_const_u8_sentinel_0;
9457 const slice_alignment = slice_ty.abiAlignment(mod);
96639458 const llvm_slice_ptr_ty = self.context.pointerType(0); // TODO: Address space
96649459
96659460 const error_name_table_global = self.dg.object.llvm_module.addGlobal(llvm_slice_ptr_ty, "__zig_err_name_table");
......@@ -9701,16 +9496,15 @@ pub const FuncGen = struct {
97019496 opt_ty: Type,
97029497 can_elide_load: bool,
97039498 ) !*llvm.Value {
9704 var buf: Type.Payload.ElemType = undefined;
9705 const payload_ty = opt_ty.optionalChild(&buf);
9499 const mod = fg.dg.module;
9500 const payload_ty = opt_ty.optionalChild(mod);
97069501
9707 if (isByRef(opt_ty)) {
9502 if (isByRef(opt_ty, mod)) {
97089503 // We have a pointer and we need to return a pointer to the first field.
97099504 const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, "");
97109505
9711 const target = fg.dg.module.getTarget();
9712 const payload_alignment = payload_ty.abiAlignment(target);
9713 if (isByRef(payload_ty)) {
9506 const payload_alignment = payload_ty.abiAlignment(mod);
9507 if (isByRef(payload_ty, mod)) {
97149508 if (can_elide_load)
97159509 return payload_ptr;
97169510
......@@ -9722,7 +9516,7 @@ pub const FuncGen = struct {
97229516 return load_inst;
97239517 }
97249518
9725 assert(!isByRef(payload_ty));
9519 assert(!isByRef(payload_ty, mod));
97269520 return fg.builder.buildExtractValue(opt_handle, 0, "");
97279521 }
97289522
......@@ -9734,10 +9528,10 @@ pub const FuncGen = struct {
97349528 ) !?*llvm.Value {
97359529 const optional_llvm_ty = try self.dg.lowerType(optional_ty);
97369530 const non_null_field = self.builder.buildZExt(non_null_bit, self.context.intType(8), "");
9531 const mod = self.dg.module;
97379532
9738 if (isByRef(optional_ty)) {
9739 const target = self.dg.module.getTarget();
9740 const payload_alignment = optional_ty.abiAlignment(target);
9533 if (isByRef(optional_ty, mod)) {
9534 const payload_alignment = optional_ty.abiAlignment(mod);
97419535 const alloca_inst = self.buildAlloca(optional_llvm_ty, payload_alignment);
97429536
97439537 {
......@@ -9765,13 +9559,13 @@ pub const FuncGen = struct {
97659559 struct_ptr_ty: Type,
97669560 field_index: u32,
97679561 ) !?*llvm.Value {
9768 const target = self.dg.object.target;
9769 const struct_ty = struct_ptr_ty.childType();
9770 switch (struct_ty.zigTypeTag()) {
9771 .Struct => switch (struct_ty.containerLayout()) {
9562 const mod = self.dg.module;
9563 const struct_ty = struct_ptr_ty.childType(mod);
9564 switch (struct_ty.zigTypeTag(mod)) {
9565 .Struct => switch (struct_ty.containerLayout(mod)) {
97729566 .Packed => {
9773 const result_ty = self.air.typeOfIndex(inst);
9774 const result_ty_info = result_ty.ptrInfo().data;
9567 const result_ty = self.typeOfIndex(inst);
9568 const result_ty_info = result_ty.ptrInfo(mod);
97759569
97769570 if (result_ty_info.host_size != 0) {
97779571 // From LLVM's perspective, a pointer to a packed struct and a pointer
......@@ -9783,7 +9577,7 @@ pub const FuncGen = struct {
97839577
97849578 // We have a pointer to a packed struct field that happens to be byte-aligned.
97859579 // Offset our operand pointer by the correct number of bytes.
9786 const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, target);
9580 const byte_offset = struct_ty.packedStructFieldByteOffset(field_index, mod);
97879581 if (byte_offset == 0) return struct_ptr;
97889582 const byte_llvm_ty = self.context.intType(8);
97899583 const llvm_usize = try self.dg.lowerType(Type.usize);
......@@ -9794,24 +9588,23 @@ pub const FuncGen = struct {
97949588 else => {
97959589 const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty);
97969590
9797 var ty_buf: Type.Payload.Pointer = undefined;
9798 if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| {
9799 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, "");
9591 if (llvmField(struct_ty, field_index, mod)) |llvm_field| {
9592 return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field.index, "");
98009593 } else {
98019594 // If we found no index then this means this is a zero sized field at the
98029595 // end of the struct. Treat our struct pointer as an array of two and get
98039596 // the index to the element at index `1` to get a pointer to the end of
98049597 // the struct.
98059598 const llvm_u32 = self.context.intType(32);
9806 const llvm_index = llvm_u32.constInt(@boolToInt(struct_ty.hasRuntimeBitsIgnoreComptime()), .False);
9599 const llvm_index = llvm_u32.constInt(@boolToInt(struct_ty.hasRuntimeBitsIgnoreComptime(mod)), .False);
98079600 const indices: [1]*llvm.Value = .{llvm_index};
98089601 return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, "");
98099602 }
98109603 },
98119604 },
98129605 .Union => {
9813 const layout = struct_ty.unionGetLayout(target);
9814 if (layout.payload_size == 0 or struct_ty.containerLayout() == .Packed) return struct_ptr;
9606 const layout = struct_ty.unionGetLayout(mod);
9607 if (layout.payload_size == 0 or struct_ty.containerLayout(mod) == .Packed) return struct_ptr;
98159608 const payload_index = @boolToInt(layout.tag_align >= layout.payload_align);
98169609 const union_llvm_ty = try self.dg.lowerType(struct_ty);
98179610 const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_ptr, payload_index, "");
......@@ -9835,12 +9628,12 @@ pub const FuncGen = struct {
98359628 ptr_alignment: u32,
98369629 is_volatile: bool,
98379630 ) !*llvm.Value {
9631 const mod = fg.dg.module;
98389632 const pointee_llvm_ty = try fg.dg.lowerType(pointee_type);
9839 const target = fg.dg.module.getTarget();
9840 const result_align = @max(ptr_alignment, pointee_type.abiAlignment(target));
9633 const result_align = @max(ptr_alignment, pointee_type.abiAlignment(mod));
98419634 const result_ptr = fg.buildAlloca(pointee_llvm_ty, result_align);
9842 const llvm_usize = fg.context.intType(Type.usize.intInfo(target).bits);
9843 const size_bytes = pointee_type.abiSize(target);
9635 const llvm_usize = fg.context.intType(Type.usize.intInfo(mod).bits);
9636 const size_bytes = pointee_type.abiSize(mod);
98449637 _ = fg.builder.buildMemCpy(
98459638 result_ptr,
98469639 result_align,
......@@ -9856,12 +9649,12 @@ pub const FuncGen = struct {
98569649 /// alloca and copies the value into it, then returns the alloca instruction.
98579650 /// For isByRef=false types, it creates a load instruction and returns it.
98589651 fn load(self: *FuncGen, ptr: *llvm.Value, ptr_ty: Type) !?*llvm.Value {
9859 const info = ptr_ty.ptrInfo().data;
9860 if (!info.pointee_type.hasRuntimeBitsIgnoreComptime()) return null;
9652 const mod = self.dg.module;
9653 const info = ptr_ty.ptrInfo(mod);
9654 if (!info.pointee_type.hasRuntimeBitsIgnoreComptime(mod)) return null;
98619655
9862 const target = self.dg.module.getTarget();
9863 const ptr_alignment = info.alignment(target);
9864 const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr());
9656 const ptr_alignment = info.alignment(mod);
9657 const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr(mod));
98659658
98669659 assert(info.vector_index != .runtime);
98679660 if (info.vector_index != .none) {
......@@ -9877,7 +9670,7 @@ pub const FuncGen = struct {
98779670 }
98789671
98799672 if (info.host_size == 0) {
9880 if (isByRef(info.pointee_type)) {
9673 if (isByRef(info.pointee_type, mod)) {
98819674 return self.loadByRef(ptr, info.pointee_type, ptr_alignment, info.@"volatile");
98829675 }
98839676 const elem_llvm_ty = try self.dg.lowerType(info.pointee_type);
......@@ -9892,13 +9685,13 @@ pub const FuncGen = struct {
98929685 containing_int.setAlignment(ptr_alignment);
98939686 containing_int.setVolatile(ptr_volatile);
98949687
9895 const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(target));
9688 const elem_bits = @intCast(c_uint, ptr_ty.childType(mod).bitSize(mod));
98969689 const shift_amt = containing_int.typeOf().constInt(info.bit_offset, .False);
98979690 const shifted_value = self.builder.buildLShr(containing_int, shift_amt, "");
98989691 const elem_llvm_ty = try self.dg.lowerType(info.pointee_type);
98999692
9900 if (isByRef(info.pointee_type)) {
9901 const result_align = info.pointee_type.abiAlignment(target);
9693 if (isByRef(info.pointee_type, mod)) {
9694 const result_align = info.pointee_type.abiAlignment(mod);
99029695 const result_ptr = self.buildAlloca(elem_llvm_ty, result_align);
99039696
99049697 const same_size_int = self.context.intType(elem_bits);
......@@ -9908,13 +9701,13 @@ pub const FuncGen = struct {
99089701 return result_ptr;
99099702 }
99109703
9911 if (info.pointee_type.zigTypeTag() == .Float or info.pointee_type.zigTypeTag() == .Vector) {
9704 if (info.pointee_type.zigTypeTag(mod) == .Float or info.pointee_type.zigTypeTag(mod) == .Vector) {
99129705 const same_size_int = self.context.intType(elem_bits);
99139706 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
99149707 return self.builder.buildBitCast(truncated_int, elem_llvm_ty, "");
99159708 }
99169709
9917 if (info.pointee_type.isPtrAtRuntime()) {
9710 if (info.pointee_type.isPtrAtRuntime(mod)) {
99189711 const same_size_int = self.context.intType(elem_bits);
99199712 const truncated_int = self.builder.buildTrunc(shifted_value, same_size_int, "");
99209713 return self.builder.buildIntToPtr(truncated_int, elem_llvm_ty, "");
......@@ -9930,13 +9723,13 @@ pub const FuncGen = struct {
99309723 elem: *llvm.Value,
99319724 ordering: llvm.AtomicOrdering,
99329725 ) !void {
9933 const info = ptr_ty.ptrInfo().data;
9726 const mod = self.dg.module;
9727 const info = ptr_ty.ptrInfo(mod);
99349728 const elem_ty = info.pointee_type;
9935 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime()) {
9729 if (!elem_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) {
99369730 return;
99379731 }
9938 const target = self.dg.module.getTarget();
9939 const ptr_alignment = ptr_ty.ptrAlignment(target);
9732 const ptr_alignment = ptr_ty.ptrAlignment(mod);
99409733 const ptr_volatile = llvm.Bool.fromBool(info.@"volatile");
99419734
99429735 assert(info.vector_index != .runtime);
......@@ -9964,13 +9757,13 @@ pub const FuncGen = struct {
99649757 assert(ordering == .NotAtomic);
99659758 containing_int.setAlignment(ptr_alignment);
99669759 containing_int.setVolatile(ptr_volatile);
9967 const elem_bits = @intCast(c_uint, ptr_ty.elemType().bitSize(target));
9760 const elem_bits = @intCast(c_uint, ptr_ty.childType(mod).bitSize(mod));
99689761 const containing_int_ty = containing_int.typeOf();
99699762 const shift_amt = containing_int_ty.constInt(info.bit_offset, .False);
99709763 // Convert to equally-sized integer type in order to perform the bit
99719764 // operations on the value to store
99729765 const value_bits_type = self.context.intType(elem_bits);
9973 const value_bits = if (elem_ty.isPtrAtRuntime())
9766 const value_bits = if (elem_ty.isPtrAtRuntime(mod))
99749767 self.builder.buildPtrToInt(elem, value_bits_type, "")
99759768 else
99769769 self.builder.buildBitCast(elem, value_bits_type, "");
......@@ -9991,7 +9784,7 @@ pub const FuncGen = struct {
99919784 store_inst.setVolatile(ptr_volatile);
99929785 return;
99939786 }
9994 if (!isByRef(elem_ty)) {
9787 if (!isByRef(elem_ty, mod)) {
99959788 const store_inst = self.builder.buildStore(elem, ptr);
99969789 store_inst.setOrdering(ordering);
99979790 store_inst.setAlignment(ptr_alignment);
......@@ -9999,13 +9792,13 @@ pub const FuncGen = struct {
99999792 return;
100009793 }
100019794 assert(ordering == .NotAtomic);
10002 const size_bytes = elem_ty.abiSize(target);
9795 const size_bytes = elem_ty.abiSize(mod);
100039796 _ = self.builder.buildMemCpy(
100049797 ptr,
100059798 ptr_alignment,
100069799 elem,
10007 elem_ty.abiAlignment(target),
10008 self.context.intType(Type.usize.intInfo(target).bits).constInt(size_bytes, .False),
9800 elem_ty.abiAlignment(mod),
9801 self.context.intType(Type.usize.intInfo(mod).bits).constInt(size_bytes, .False),
100099802 info.@"volatile",
100109803 );
100119804 }
......@@ -10030,11 +9823,12 @@ pub const FuncGen = struct {
100309823 a4: *llvm.Value,
100319824 a5: *llvm.Value,
100329825 ) *llvm.Value {
10033 const target = fg.dg.module.getTarget();
9826 const mod = fg.dg.module;
9827 const target = mod.getTarget();
100349828 if (!target_util.hasValgrindSupport(target)) return default_value;
100359829
100369830 const usize_llvm_ty = fg.context.intType(target.ptrBitWidth());
10037 const usize_alignment = @intCast(c_uint, Type.usize.abiSize(target));
9831 const usize_alignment = @intCast(c_uint, Type.usize.abiSize(mod));
100389832
100399833 const array_llvm_ty = usize_llvm_ty.arrayType(6);
100409834 const array_ptr = fg.valgrind_client_request_array orelse a: {
......@@ -10111,6 +9905,16 @@ pub const FuncGen = struct {
101119905 );
101129906 return call;
101139907 }
9908
9909 fn typeOf(fg: *FuncGen, inst: Air.Inst.Ref) Type {
9910 const mod = fg.dg.module;
9911 return fg.air.typeOf(inst, &mod.intern_pool);
9912 }
9913
9914 fn typeOfIndex(fg: *FuncGen, inst: Air.Inst.Index) Type {
9915 const mod = fg.dg.module;
9916 return fg.air.typeOfIndex(inst, &mod.intern_pool);
9917 }
101149918};
101159919
101169920fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {
......@@ -10444,62 +10248,64 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ
1044410248 };
1044510249}
1044610250
10251const LlvmField = struct {
10252 index: c_uint,
10253 ty: Type,
10254 alignment: u32,
10255};
10256
1044710257/// Take into account 0 bit fields and padding. Returns null if an llvm
1044810258/// field could not be found.
1044910259/// This only happens if you want the field index of a zero sized field at
1045010260/// the end of the struct.
10451fn llvmFieldIndex(
10452 ty: Type,
10453 field_index: usize,
10454 target: std.Target,
10455 ptr_pl_buf: *Type.Payload.Pointer,
10456) ?c_uint {
10261fn llvmField(ty: Type, field_index: usize, mod: *Module) ?LlvmField {
1045710262 // Detects where we inserted extra padding fields so that we can skip
1045810263 // over them in this function.
1045910264 comptime assert(struct_layout_version == 2);
1046010265 var offset: u64 = 0;
1046110266 var big_align: u32 = 0;
1046210267
10463 if (ty.isSimpleTupleOrAnonStruct()) {
10464 const tuple = ty.tupleFields();
10465 var llvm_field_index: c_uint = 0;
10466 for (tuple.types, 0..) |field_ty, i| {
10467 if (tuple.values[i].tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
10268 const struct_type = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
10269 .anon_struct_type => |tuple| {
10270 var llvm_field_index: c_uint = 0;
10271 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
10272 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
1046810273
10469 const field_align = field_ty.abiAlignment(target);
10470 big_align = @max(big_align, field_align);
10471 const prev_offset = offset;
10472 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
10274 const field_align = field_ty.toType().abiAlignment(mod);
10275 big_align = @max(big_align, field_align);
10276 const prev_offset = offset;
10277 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
1047310278
10474 const padding_len = offset - prev_offset;
10475 if (padding_len > 0) {
10476 llvm_field_index += 1;
10477 }
10279 const padding_len = offset - prev_offset;
10280 if (padding_len > 0) {
10281 llvm_field_index += 1;
10282 }
1047810283
10479 if (field_index <= i) {
10480 ptr_pl_buf.* = .{
10481 .data = .{
10482 .pointee_type = field_ty,
10483 .@"align" = field_align,
10484 .@"addrspace" = .generic,
10485 },
10486 };
10487 return llvm_field_index;
10488 }
10284 if (field_index <= i) {
10285 return .{
10286 .index = llvm_field_index,
10287 .ty = field_ty.toType(),
10288 .alignment = field_align,
10289 };
10290 }
1048910291
10490 llvm_field_index += 1;
10491 offset += field_ty.abiSize(target);
10492 }
10493 return null;
10494 }
10495 const layout = ty.containerLayout();
10292 llvm_field_index += 1;
10293 offset += field_ty.toType().abiSize(mod);
10294 }
10295 return null;
10296 },
10297 .struct_type => |s| s,
10298 else => unreachable,
10299 };
10300 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
10301 const layout = struct_obj.layout;
1049610302 assert(layout != .Packed);
1049710303
1049810304 var llvm_field_index: c_uint = 0;
10499 var it = ty.castTag(.@"struct").?.data.runtimeFieldIterator();
10305 var it = struct_obj.runtimeFieldIterator(mod);
1050010306 while (it.next()) |field_and_index| {
1050110307 const field = field_and_index.field;
10502 const field_align = field.alignment(target, layout);
10308 const field_align = field.alignment(mod, layout);
1050310309 big_align = @max(big_align, field_align);
1050410310 const prev_offset = offset;
1050510311 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
......@@ -10510,54 +10316,52 @@ fn llvmFieldIndex(
1051010316 }
1051110317
1051210318 if (field_index == field_and_index.index) {
10513 ptr_pl_buf.* = .{
10514 .data = .{
10515 .pointee_type = field.ty,
10516 .@"align" = field_align,
10517 .@"addrspace" = .generic,
10518 },
10319 return .{
10320 .index = llvm_field_index,
10321 .ty = field.ty,
10322 .alignment = field_align,
1051910323 };
10520 return llvm_field_index;
1052110324 }
1052210325
1052310326 llvm_field_index += 1;
10524 offset += field.ty.abiSize(target);
10327 offset += field.ty.abiSize(mod);
1052510328 } else {
1052610329 // We did not find an llvm field that corresponds to this zig field.
1052710330 return null;
1052810331 }
1052910332}
1053010333
10531fn firstParamSRet(fn_info: Type.Payload.Function.Data, target: std.Target) bool {
10532 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime()) return false;
10334fn firstParamSRet(fn_info: InternPool.Key.FuncType, mod: *Module) bool {
10335 if (!fn_info.return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) return false;
1053310336
10337 const target = mod.getTarget();
1053410338 switch (fn_info.cc) {
10535 .Unspecified, .Inline => return isByRef(fn_info.return_type),
10339 .Unspecified, .Inline => return isByRef(fn_info.return_type.toType(), mod),
1053610340 .C => switch (target.cpu.arch) {
1053710341 .mips, .mipsel => return false,
1053810342 .x86_64 => switch (target.os.tag) {
10539 .windows => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,
10540 else => return firstParamSRetSystemV(fn_info.return_type, target),
10343 .windows => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10344 else => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
1054110345 },
10542 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type, target)[0] == .indirect,
10543 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type, target) == .memory,
10544 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type, target, .ret)) {
10346 .wasm32 => return wasm_c_abi.classifyType(fn_info.return_type.toType(), mod)[0] == .indirect,
10347 .aarch64, .aarch64_be => return aarch64_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
10348 .arm, .armeb => switch (arm_c_abi.classifyType(fn_info.return_type.toType(), mod, .ret)) {
1054510349 .memory, .i64_array => return true,
1054610350 .i32_array => |size| return size != 1,
1054710351 .byval => return false,
1054810352 },
10549 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type, target) == .memory,
10353 .riscv32, .riscv64 => return riscv_c_abi.classifyType(fn_info.return_type.toType(), mod) == .memory,
1055010354 else => return false, // TODO investigate C ABI for other architectures
1055110355 },
10552 .SysV => return firstParamSRetSystemV(fn_info.return_type, target),
10553 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type, target) == .memory,
10554 .Stdcall => return !isScalar(fn_info.return_type),
10356 .SysV => return firstParamSRetSystemV(fn_info.return_type.toType(), mod),
10357 .Win64 => return x86_64_abi.classifyWindows(fn_info.return_type.toType(), mod) == .memory,
10358 .Stdcall => return !isScalar(mod, fn_info.return_type.toType()),
1055510359 else => return false,
1055610360 }
1055710361}
1055810362
10559fn firstParamSRetSystemV(ty: Type, target: std.Target) bool {
10560 const class = x86_64_abi.classifySystemV(ty, target, .ret);
10363fn firstParamSRetSystemV(ty: Type, mod: *Module) bool {
10364 const class = x86_64_abi.classifySystemV(ty, mod, .ret);
1056110365 if (class[0] == .memory) return true;
1056210366 if (class[0] == .x87 and class[2] != .none) return true;
1056310367 return false;
......@@ -10566,75 +10370,77 @@ fn firstParamSRetSystemV(ty: Type, target: std.Target) bool {
1056610370/// In order to support the C calling convention, some return types need to be lowered
1056710371/// completely differently in the function prototype to honor the C ABI, and then
1056810372/// be effectively bitcasted to the actual return type.
10569fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10570 if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime()) {
10373fn lowerFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10374 const mod = dg.module;
10375 const return_type = fn_info.return_type.toType();
10376 if (!return_type.hasRuntimeBitsIgnoreComptime(mod)) {
1057110377 // If the return type is an error set or an error union, then we make this
1057210378 // anyerror return type instead, so that it can be coerced into a function
1057310379 // pointer type which has anyerror as the return type.
10574 if (fn_info.return_type.isError()) {
10380 if (return_type.isError(mod)) {
1057510381 return dg.lowerType(Type.anyerror);
1057610382 } else {
1057710383 return dg.context.voidType();
1057810384 }
1057910385 }
10580 const target = dg.module.getTarget();
10386 const target = mod.getTarget();
1058110387 switch (fn_info.cc) {
1058210388 .Unspecified, .Inline => {
10583 if (isByRef(fn_info.return_type)) {
10389 if (isByRef(return_type, mod)) {
1058410390 return dg.context.voidType();
1058510391 } else {
10586 return dg.lowerType(fn_info.return_type);
10392 return dg.lowerType(return_type);
1058710393 }
1058810394 },
1058910395 .C => {
1059010396 switch (target.cpu.arch) {
10591 .mips, .mipsel => return dg.lowerType(fn_info.return_type),
10397 .mips, .mipsel => return dg.lowerType(return_type),
1059210398 .x86_64 => switch (target.os.tag) {
1059310399 .windows => return lowerWin64FnRetTy(dg, fn_info),
1059410400 else => return lowerSystemVFnRetTy(dg, fn_info),
1059510401 },
1059610402 .wasm32 => {
10597 if (isScalar(fn_info.return_type)) {
10598 return dg.lowerType(fn_info.return_type);
10403 if (isScalar(mod, return_type)) {
10404 return dg.lowerType(return_type);
1059910405 }
10600 const classes = wasm_c_abi.classifyType(fn_info.return_type, target);
10406 const classes = wasm_c_abi.classifyType(return_type, mod);
1060110407 if (classes[0] == .indirect or classes[0] == .none) {
1060210408 return dg.context.voidType();
1060310409 }
1060410410
1060510411 assert(classes[0] == .direct and classes[1] == .none);
10606 const scalar_type = wasm_c_abi.scalarType(fn_info.return_type, target);
10607 const abi_size = scalar_type.abiSize(target);
10412 const scalar_type = wasm_c_abi.scalarType(return_type, mod);
10413 const abi_size = scalar_type.abiSize(mod);
1060810414 return dg.context.intType(@intCast(c_uint, abi_size * 8));
1060910415 },
1061010416 .aarch64, .aarch64_be => {
10611 switch (aarch64_c_abi.classifyType(fn_info.return_type, target)) {
10417 switch (aarch64_c_abi.classifyType(return_type, mod)) {
1061210418 .memory => return dg.context.voidType(),
10613 .float_array => return dg.lowerType(fn_info.return_type),
10614 .byval => return dg.lowerType(fn_info.return_type),
10419 .float_array => return dg.lowerType(return_type),
10420 .byval => return dg.lowerType(return_type),
1061510421 .integer => {
10616 const bit_size = fn_info.return_type.bitSize(target);
10422 const bit_size = return_type.bitSize(mod);
1061710423 return dg.context.intType(@intCast(c_uint, bit_size));
1061810424 },
1061910425 .double_integer => return dg.context.intType(64).arrayType(2),
1062010426 }
1062110427 },
1062210428 .arm, .armeb => {
10623 switch (arm_c_abi.classifyType(fn_info.return_type, target, .ret)) {
10429 switch (arm_c_abi.classifyType(return_type, mod, .ret)) {
1062410430 .memory, .i64_array => return dg.context.voidType(),
1062510431 .i32_array => |len| if (len == 1) {
1062610432 return dg.context.intType(32);
1062710433 } else {
1062810434 return dg.context.voidType();
1062910435 },
10630 .byval => return dg.lowerType(fn_info.return_type),
10436 .byval => return dg.lowerType(return_type),
1063110437 }
1063210438 },
1063310439 .riscv32, .riscv64 => {
10634 switch (riscv_c_abi.classifyType(fn_info.return_type, target)) {
10440 switch (riscv_c_abi.classifyType(return_type, mod)) {
1063510441 .memory => return dg.context.voidType(),
1063610442 .integer => {
10637 const bit_size = fn_info.return_type.bitSize(target);
10443 const bit_size = return_type.bitSize(mod);
1063810444 return dg.context.intType(@intCast(c_uint, bit_size));
1063910445 },
1064010446 .double_integer => {
......@@ -10644,50 +10450,52 @@ fn lowerFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
1064410450 };
1064510451 return dg.context.structType(&llvm_types_buffer, 2, .False);
1064610452 },
10647 .byval => return dg.lowerType(fn_info.return_type),
10453 .byval => return dg.lowerType(return_type),
1064810454 }
1064910455 },
1065010456 // TODO investigate C ABI for other architectures
10651 else => return dg.lowerType(fn_info.return_type),
10457 else => return dg.lowerType(return_type),
1065210458 }
1065310459 },
1065410460 .Win64 => return lowerWin64FnRetTy(dg, fn_info),
1065510461 .SysV => return lowerSystemVFnRetTy(dg, fn_info),
1065610462 .Stdcall => {
10657 if (isScalar(fn_info.return_type)) {
10658 return dg.lowerType(fn_info.return_type);
10463 if (isScalar(mod, return_type)) {
10464 return dg.lowerType(return_type);
1065910465 } else {
1066010466 return dg.context.voidType();
1066110467 }
1066210468 },
10663 else => return dg.lowerType(fn_info.return_type),
10469 else => return dg.lowerType(return_type),
1066410470 }
1066510471}
1066610472
10667fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10668 const target = dg.module.getTarget();
10669 switch (x86_64_abi.classifyWindows(fn_info.return_type, target)) {
10473fn lowerWin64FnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10474 const mod = dg.module;
10475 const return_type = fn_info.return_type.toType();
10476 switch (x86_64_abi.classifyWindows(return_type, mod)) {
1067010477 .integer => {
10671 if (isScalar(fn_info.return_type)) {
10672 return dg.lowerType(fn_info.return_type);
10478 if (isScalar(mod, return_type)) {
10479 return dg.lowerType(return_type);
1067310480 } else {
10674 const abi_size = fn_info.return_type.abiSize(target);
10481 const abi_size = return_type.abiSize(mod);
1067510482 return dg.context.intType(@intCast(c_uint, abi_size * 8));
1067610483 }
1067710484 },
1067810485 .win_i128 => return dg.context.intType(64).vectorType(2),
1067910486 .memory => return dg.context.voidType(),
10680 .sse => return dg.lowerType(fn_info.return_type),
10487 .sse => return dg.lowerType(return_type),
1068110488 else => unreachable,
1068210489 }
1068310490}
1068410491
10685fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm.Type {
10686 if (isScalar(fn_info.return_type)) {
10687 return dg.lowerType(fn_info.return_type);
10492fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: InternPool.Key.FuncType) !*llvm.Type {
10493 const mod = dg.module;
10494 const return_type = fn_info.return_type.toType();
10495 if (isScalar(mod, return_type)) {
10496 return dg.lowerType(return_type);
1068810497 }
10689 const target = dg.module.getTarget();
10690 const classes = x86_64_abi.classifySystemV(fn_info.return_type, target, .ret);
10498 const classes = x86_64_abi.classifySystemV(return_type, mod, .ret);
1069110499 if (classes[0] == .memory) {
1069210500 return dg.context.voidType();
1069310501 }
......@@ -10728,7 +10536,7 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
1072810536 }
1072910537 }
1073010538 if (classes[0] == .integer and classes[1] == .none) {
10731 const abi_size = fn_info.return_type.abiSize(target);
10539 const abi_size = return_type.abiSize(mod);
1073210540 return dg.context.intType(@intCast(c_uint, abi_size * 8));
1073310541 }
1073410542 return dg.context.structType(&llvm_types_buffer, llvm_types_index, .False);
......@@ -10736,10 +10544,9 @@ fn lowerSystemVFnRetTy(dg: *DeclGen, fn_info: Type.Payload.Function.Data) !*llvm
1073610544
1073710545const ParamTypeIterator = struct {
1073810546 dg: *DeclGen,
10739 fn_info: Type.Payload.Function.Data,
10547 fn_info: InternPool.Key.FuncType,
1074010548 zig_index: u32,
1074110549 llvm_index: u32,
10742 target: std.Target,
1074310550 llvm_types_len: u32,
1074410551 llvm_types_buffer: [8]*llvm.Type,
1074510552 byval_attr: bool,
......@@ -10762,7 +10569,7 @@ const ParamTypeIterator = struct {
1076210569 if (it.zig_index >= it.fn_info.param_types.len) return null;
1076310570 const ty = it.fn_info.param_types[it.zig_index];
1076410571 it.byval_attr = false;
10765 return nextInner(it, ty);
10572 return nextInner(it, ty.toType());
1076610573 }
1076710574
1076810575 /// `airCall` uses this instead of `next` so that it can take into account variadic functions.
......@@ -10771,15 +10578,18 @@ const ParamTypeIterator = struct {
1077110578 if (it.zig_index >= args.len) {
1077210579 return null;
1077310580 } else {
10774 return nextInner(it, fg.air.typeOf(args[it.zig_index]));
10581 return nextInner(it, fg.typeOf(args[it.zig_index]));
1077510582 }
1077610583 } else {
10777 return nextInner(it, it.fn_info.param_types[it.zig_index]);
10584 return nextInner(it, it.fn_info.param_types[it.zig_index].toType());
1077810585 }
1077910586 }
1078010587
1078110588 fn nextInner(it: *ParamTypeIterator, ty: Type) ?Lowering {
10782 if (!ty.hasRuntimeBitsIgnoreComptime()) {
10589 const mod = it.dg.module;
10590 const target = mod.getTarget();
10591
10592 if (!ty.hasRuntimeBitsIgnoreComptime(mod)) {
1078310593 it.zig_index += 1;
1078410594 return .no_bits;
1078510595 }
......@@ -10787,11 +10597,10 @@ const ParamTypeIterator = struct {
1078710597 .Unspecified, .Inline => {
1078810598 it.zig_index += 1;
1078910599 it.llvm_index += 1;
10790 var buf: Type.Payload.ElemType = undefined;
10791 if (ty.isSlice() or (ty.zigTypeTag() == .Optional and ty.optionalChild(&buf).isSlice())) {
10600 if (ty.isSlice(mod) or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(mod).isSlice(mod))) {
1079210601 it.llvm_index += 1;
1079310602 return .slice;
10794 } else if (isByRef(ty)) {
10603 } else if (isByRef(ty, mod)) {
1079510604 return .byref;
1079610605 } else {
1079710606 return .byval;
......@@ -10801,23 +10610,23 @@ const ParamTypeIterator = struct {
1080110610 @panic("TODO implement async function lowering in the LLVM backend");
1080210611 },
1080310612 .C => {
10804 switch (it.target.cpu.arch) {
10613 switch (target.cpu.arch) {
1080510614 .mips, .mipsel => {
1080610615 it.zig_index += 1;
1080710616 it.llvm_index += 1;
1080810617 return .byval;
1080910618 },
10810 .x86_64 => switch (it.target.os.tag) {
10619 .x86_64 => switch (target.os.tag) {
1081110620 .windows => return it.nextWin64(ty),
1081210621 else => return it.nextSystemV(ty),
1081310622 },
1081410623 .wasm32 => {
1081510624 it.zig_index += 1;
1081610625 it.llvm_index += 1;
10817 if (isScalar(ty)) {
10626 if (isScalar(mod, ty)) {
1081810627 return .byval;
1081910628 }
10820 const classes = wasm_c_abi.classifyType(ty, it.target);
10629 const classes = wasm_c_abi.classifyType(ty, mod);
1082110630 if (classes[0] == .indirect) {
1082210631 return .byref;
1082310632 }
......@@ -10826,7 +10635,7 @@ const ParamTypeIterator = struct {
1082610635 .aarch64, .aarch64_be => {
1082710636 it.zig_index += 1;
1082810637 it.llvm_index += 1;
10829 switch (aarch64_c_abi.classifyType(ty, it.target)) {
10638 switch (aarch64_c_abi.classifyType(ty, mod)) {
1083010639 .memory => return .byref_mut,
1083110640 .float_array => |len| return Lowering{ .float_array = len },
1083210641 .byval => return .byval,
......@@ -10841,7 +10650,7 @@ const ParamTypeIterator = struct {
1084110650 .arm, .armeb => {
1084210651 it.zig_index += 1;
1084310652 it.llvm_index += 1;
10844 switch (arm_c_abi.classifyType(ty, it.target, .arg)) {
10653 switch (arm_c_abi.classifyType(ty, mod, .arg)) {
1084510654 .memory => {
1084610655 it.byval_attr = true;
1084710656 return .byref;
......@@ -10854,10 +10663,10 @@ const ParamTypeIterator = struct {
1085410663 .riscv32, .riscv64 => {
1085510664 it.zig_index += 1;
1085610665 it.llvm_index += 1;
10857 if (ty.tag() == .f16) {
10666 if (ty.toIntern() == .f16_type) {
1085810667 return .as_u16;
1085910668 }
10860 switch (riscv_c_abi.classifyType(ty, it.target)) {
10669 switch (riscv_c_abi.classifyType(ty, mod)) {
1086110670 .memory => return .byref_mut,
1086210671 .byval => return .byval,
1086310672 .integer => return .abi_sized_int,
......@@ -10878,7 +10687,7 @@ const ParamTypeIterator = struct {
1087810687 it.zig_index += 1;
1087910688 it.llvm_index += 1;
1088010689
10881 if (isScalar(ty)) {
10690 if (isScalar(mod, ty)) {
1088210691 return .byval;
1088310692 } else {
1088410693 it.byval_attr = true;
......@@ -10894,9 +10703,10 @@ const ParamTypeIterator = struct {
1089410703 }
1089510704
1089610705 fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering {
10897 switch (x86_64_abi.classifyWindows(ty, it.target)) {
10706 const mod = it.dg.module;
10707 switch (x86_64_abi.classifyWindows(ty, mod)) {
1089810708 .integer => {
10899 if (isScalar(ty)) {
10709 if (isScalar(mod, ty)) {
1090010710 it.zig_index += 1;
1090110711 it.llvm_index += 1;
1090210712 return .byval;
......@@ -10926,14 +10736,15 @@ const ParamTypeIterator = struct {
1092610736 }
1092710737
1092810738 fn nextSystemV(it: *ParamTypeIterator, ty: Type) ?Lowering {
10929 const classes = x86_64_abi.classifySystemV(ty, it.target, .arg);
10739 const mod = it.dg.module;
10740 const classes = x86_64_abi.classifySystemV(ty, mod, .arg);
1093010741 if (classes[0] == .memory) {
1093110742 it.zig_index += 1;
1093210743 it.llvm_index += 1;
1093310744 it.byval_attr = true;
1093410745 return .byref;
1093510746 }
10936 if (isScalar(ty)) {
10747 if (isScalar(mod, ty)) {
1093710748 it.zig_index += 1;
1093810749 it.llvm_index += 1;
1093910750 return .byval;
......@@ -10986,13 +10797,12 @@ const ParamTypeIterator = struct {
1098610797 }
1098710798};
1098810799
10989fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTypeIterator {
10800fn iterateParamTypes(dg: *DeclGen, fn_info: InternPool.Key.FuncType) ParamTypeIterator {
1099010801 return .{
1099110802 .dg = dg,
1099210803 .fn_info = fn_info,
1099310804 .zig_index = 0,
1099410805 .llvm_index = 0,
10995 .target = dg.module.getTarget(),
1099610806 .llvm_types_buffer = undefined,
1099710807 .llvm_types_len = 0,
1099810808 .byval_attr = false,
......@@ -11001,16 +10811,17 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp
1100110811
1100210812fn ccAbiPromoteInt(
1100310813 cc: std.builtin.CallingConvention,
11004 target: std.Target,
10814 mod: *Module,
1100510815 ty: Type,
1100610816) ?std.builtin.Signedness {
10817 const target = mod.getTarget();
1100710818 switch (cc) {
1100810819 .Unspecified, .Inline, .Async => return null,
1100910820 else => {},
1101010821 }
11011 const int_info = switch (ty.zigTypeTag()) {
11012 .Bool => Type.u1.intInfo(target),
11013 .Int, .Enum, .ErrorSet => ty.intInfo(target),
10822 const int_info = switch (ty.zigTypeTag(mod)) {
10823 .Bool => Type.u1.intInfo(mod),
10824 .Int, .Enum, .ErrorSet => ty.intInfo(mod),
1101410825 else => return null,
1101510826 };
1101610827 if (int_info.bits <= 16) return int_info.signedness;
......@@ -11039,12 +10850,12 @@ fn ccAbiPromoteInt(
1103910850
1104010851/// This is the one source of truth for whether a type is passed around as an LLVM pointer,
1104110852/// or as an LLVM value.
11042fn isByRef(ty: Type) bool {
10853fn isByRef(ty: Type, mod: *Module) bool {
1104310854 // For tuples and structs, if there are more than this many non-void
1104410855 // fields, then we make it byref, otherwise byval.
1104510856 const max_fields_byval = 0;
1104610857
11047 switch (ty.zigTypeTag()) {
10858 switch (ty.zigTypeTag(mod)) {
1104810859 .Type,
1104910860 .ComptimeInt,
1105010861 .ComptimeFloat,
......@@ -11067,51 +10878,53 @@ fn isByRef(ty: Type) bool {
1106710878 .AnyFrame,
1106810879 => return false,
1106910880
11070 .Array, .Frame => return ty.hasRuntimeBits(),
10881 .Array, .Frame => return ty.hasRuntimeBits(mod),
1107110882 .Struct => {
1107210883 // Packed structs are represented to LLVM as integers.
11073 if (ty.containerLayout() == .Packed) return false;
11074 if (ty.isSimpleTupleOrAnonStruct()) {
11075 const tuple = ty.tupleFields();
11076 var count: usize = 0;
11077 for (tuple.values, 0..) |field_val, i| {
11078 if (field_val.tag() != .unreachable_value or !tuple.types[i].hasRuntimeBits()) continue;
11079
11080 count += 1;
11081 if (count > max_fields_byval) return true;
11082 if (isByRef(tuple.types[i])) return true;
11083 }
11084 return false;
11085 }
10884 if (ty.containerLayout(mod) == .Packed) return false;
10885 const struct_type = switch (mod.intern_pool.indexToKey(ty.toIntern())) {
10886 .anon_struct_type => |tuple| {
10887 var count: usize = 0;
10888 for (tuple.types, tuple.values) |field_ty, field_val| {
10889 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) continue;
10890
10891 count += 1;
10892 if (count > max_fields_byval) return true;
10893 if (isByRef(field_ty.toType(), mod)) return true;
10894 }
10895 return false;
10896 },
10897 .struct_type => |s| s,
10898 else => unreachable,
10899 };
10900 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1108610901 var count: usize = 0;
11087 const fields = ty.structFields();
11088 for (fields.values()) |field| {
11089 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
10902 for (struct_obj.fields.values()) |field| {
10903 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
1109010904
1109110905 count += 1;
1109210906 if (count > max_fields_byval) return true;
11093 if (isByRef(field.ty)) return true;
10907 if (isByRef(field.ty, mod)) return true;
1109410908 }
1109510909 return false;
1109610910 },
11097 .Union => switch (ty.containerLayout()) {
10911 .Union => switch (ty.containerLayout(mod)) {
1109810912 .Packed => return false,
11099 else => return ty.hasRuntimeBits(),
10913 else => return ty.hasRuntimeBits(mod),
1110010914 },
1110110915 .ErrorUnion => {
11102 const payload_ty = ty.errorUnionPayload();
11103 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
10916 const payload_ty = ty.errorUnionPayload(mod);
10917 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1110410918 return false;
1110510919 }
1110610920 return true;
1110710921 },
1110810922 .Optional => {
11109 var buf: Type.Payload.ElemType = undefined;
11110 const payload_ty = ty.optionalChild(&buf);
11111 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
10923 const payload_ty = ty.optionalChild(mod);
10924 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
1111210925 return false;
1111310926 }
11114 if (ty.optionalReprIsPayload()) {
10927 if (ty.optionalReprIsPayload(mod)) {
1111510928 return false;
1111610929 }
1111710930 return true;
......@@ -11119,8 +10932,8 @@ fn isByRef(ty: Type) bool {
1111910932 }
1112010933}
1112110934
11122fn isScalar(ty: Type) bool {
11123 return switch (ty.zigTypeTag()) {
10935fn isScalar(mod: *Module, ty: Type) bool {
10936 return switch (ty.zigTypeTag(mod)) {
1112410937 .Void,
1112510938 .Bool,
1112610939 .NoReturn,
......@@ -11134,8 +10947,8 @@ fn isScalar(ty: Type) bool {
1113410947 .Vector,
1113510948 => true,
1113610949
11137 .Struct => ty.containerLayout() == .Packed,
11138 .Union => ty.containerLayout() == .Packed,
10950 .Struct => ty.containerLayout(mod) == .Packed,
10951 .Union => ty.containerLayout(mod) == .Packed,
1113910952 else => false,
1114010953 };
1114110954}
......@@ -11184,10 +10997,10 @@ fn backendSupportsF128(target: std.Target) bool {
1118410997/// LLVM does not support all relevant intrinsics for all targets, so we
1118510998/// may need to manually generate a libc call
1118610999fn intrinsicsAllowed(scalar_ty: Type, target: std.Target) bool {
11187 return switch (scalar_ty.tag()) {
11188 .f16 => backendSupportsF16(target),
11189 .f80 => (target.c_type_bit_size(.longdouble) == 80) and backendSupportsF80(target),
11190 .f128 => (target.c_type_bit_size(.longdouble) == 128) and backendSupportsF128(target),
11000 return switch (scalar_ty.toIntern()) {
11001 .f16_type => backendSupportsF16(target),
11002 .f80_type => (target.c_type_bit_size(.longdouble) == 80) and backendSupportsF80(target),
11003 .f128_type => (target.c_type_bit_size(.longdouble) == 128) and backendSupportsF128(target),
1119111004 else => true,
1119211005 };
1119311006}
......@@ -11304,12 +11117,12 @@ fn buildAllocaInner(
1130411117 return alloca;
1130511118}
1130611119
11307fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u1 {
11308 return @boolToInt(Type.anyerror.abiAlignment(target) > payload_ty.abiAlignment(target));
11120fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 {
11121 return @boolToInt(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod));
1130911122}
1131011123
11311fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u1 {
11312 return @boolToInt(Type.anyerror.abiAlignment(target) <= payload_ty.abiAlignment(target));
11124fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 {
11125 return @boolToInt(Type.anyerror.abiAlignment(mod) <= payload_ty.abiAlignment(mod));
1131311126}
1131411127
1131511128/// Returns true for asm constraint (e.g. "=*m", "=r") if it accepts a memory location
src/codegen/spirv.zig+414-417
......@@ -218,8 +218,9 @@ pub const DeclGen = struct {
218218
219219 pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
220220 @setCold(true);
221 const mod = self.module;
221222 const src = LazySrcLoc.nodeOffset(0);
222 const src_loc = src.toSrcLoc(self.module.declPtr(self.decl_index));
223 const src_loc = src.toSrcLoc(self.module.declPtr(self.decl_index), mod);
223224 assert(self.error_msg == null);
224225 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
225226 return error.CodegenFail;
......@@ -231,12 +232,13 @@ pub const DeclGen = struct {
231232
232233 /// Fetch the result-id for a previously generated instruction or constant.
233234 fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {
234 if (self.air.value(inst)) |val| {
235 const ty = self.air.typeOf(inst);
236 if (ty.zigTypeTag() == .Fn) {
237 const fn_decl_index = switch (val.tag()) {
238 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
239 .function => val.castTag(.function).?.data.owner_decl,
235 const mod = self.module;
236 if (try self.air.value(inst, mod)) |val| {
237 const ty = self.typeOf(inst);
238 if (ty.zigTypeTag(mod) == .Fn) {
239 const fn_decl_index = switch (mod.intern_pool.indexToKey(val.ip_index)) {
240 .extern_func => |extern_func| extern_func.decl,
241 .func => |func| mod.funcPtr(func.index).owner_decl,
240242 else => unreachable,
241243 };
242244 const spv_decl_index = try self.resolveDecl(fn_decl_index);
......@@ -254,12 +256,12 @@ pub const DeclGen = struct {
254256 /// Note: Function does not actually generate the decl.
255257 fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
256258 const decl = self.module.declPtr(decl_index);
257 self.module.markDeclAlive(decl);
259 try self.module.markDeclAlive(decl);
258260
259261 const entry = try self.decl_link.getOrPut(decl_index);
260262 if (!entry.found_existing) {
261263 // TODO: Extern fn?
262 const kind: SpvModule.DeclKind = if (decl.val.tag() == .function)
264 const kind: SpvModule.DeclKind = if (decl.val.getFunctionIndex(self.module) != .none)
263265 .func
264266 else
265267 .global;
......@@ -340,8 +342,9 @@ pub const DeclGen = struct {
340342 }
341343
342344 fn arithmeticTypeInfo(self: *DeclGen, ty: Type) !ArithmeticTypeInfo {
345 const mod = self.module;
343346 const target = self.getTarget();
344 return switch (ty.zigTypeTag()) {
347 return switch (ty.zigTypeTag(mod)) {
345348 .Bool => ArithmeticTypeInfo{
346349 .bits = 1, // Doesn't matter for this class.
347350 .is_vector = false,
......@@ -355,7 +358,7 @@ pub const DeclGen = struct {
355358 .class = .float,
356359 },
357360 .Int => blk: {
358 const int_info = ty.intInfo(target);
361 const int_info = ty.intInfo(mod);
359362 // TODO: Maybe it's useful to also return this value.
360363 const maybe_backing_bits = self.backingIntBits(int_info.bits);
361364 break :blk ArithmeticTypeInfo{
......@@ -533,34 +536,35 @@ pub const DeclGen = struct {
533536 }
534537
535538 fn addInt(self: *@This(), ty: Type, val: Value) !void {
536 const target = self.dg.getTarget();
537 const int_info = ty.intInfo(target);
539 const mod = self.dg.module;
540 const int_info = ty.intInfo(mod);
538541 const int_bits = switch (int_info.signedness) {
539 .signed => @bitCast(u64, val.toSignedInt(target)),
540 .unsigned => val.toUnsignedInt(target),
542 .signed => @bitCast(u64, val.toSignedInt(mod)),
543 .unsigned => val.toUnsignedInt(mod),
541544 };
542545
543546 // TODO: Swap endianess if the compiler is big endian.
544 const len = ty.abiSize(target);
547 const len = ty.abiSize(mod);
545548 try self.addBytes(std.mem.asBytes(&int_bits)[0..@intCast(usize, len)]);
546549 }
547550
548551 fn addFloat(self: *@This(), ty: Type, val: Value) !void {
552 const mod = self.dg.module;
549553 const target = self.dg.getTarget();
550 const len = ty.abiSize(target);
554 const len = ty.abiSize(mod);
551555
552556 // TODO: Swap endianess if the compiler is big endian.
553557 switch (ty.floatBits(target)) {
554558 16 => {
555 const float_bits = val.toFloat(f16);
559 const float_bits = val.toFloat(f16, mod);
556560 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
557561 },
558562 32 => {
559 const float_bits = val.toFloat(f32);
563 const float_bits = val.toFloat(f32, mod);
560564 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
561565 },
562566 64 => {
563 const float_bits = val.toFloat(f64);
567 const float_bits = val.toFloat(f64, mod);
564568 try self.addBytes(std.mem.asBytes(&float_bits)[0..@intCast(usize, len)]);
565569 },
566570 else => unreachable,
......@@ -569,6 +573,7 @@ pub const DeclGen = struct {
569573
570574 fn addDeclRef(self: *@This(), ty: Type, decl_index: Decl.Index) !void {
571575 const dg = self.dg;
576 const mod = dg.module;
572577
573578 const ty_ref = try self.dg.resolveType(ty, .indirect);
574579 const ty_id = dg.typeId(ty_ref);
......@@ -576,19 +581,18 @@ pub const DeclGen = struct {
576581 const decl = dg.module.declPtr(decl_index);
577582 const spv_decl_index = try dg.resolveDecl(decl_index);
578583
579 switch (decl.val.tag()) {
580 .function => {
584 switch (mod.intern_pool.indexToKey(decl.val.ip_index)) {
585 .func => {
581586 // TODO: Properly lower function pointers. For now we are going to hack around it and
582587 // just generate an empty pointer. Function pointers are represented by usize for now,
583588 // though.
584 try self.addInt(Type.usize, Value.initTag(.zero));
589 try self.addInt(Type.usize, Value.zero_usize);
585590 // TODO: Add dependency
586591 return;
587592 },
588 .extern_fn => unreachable, // TODO
593 .extern_func => unreachable, // TODO
589594 else => {
590595 const result_id = dg.spv.allocId();
591 log.debug("addDeclRef: id = {}, index = {}, name = {s}", .{ result_id.id, @enumToInt(spv_decl_index), decl.name });
592596
593597 try self.decl_deps.put(spv_decl_index, {});
594598
......@@ -606,117 +610,122 @@ pub const DeclGen = struct {
606610 }
607611 }
608612
609 fn lower(self: *@This(), ty: Type, val: Value) !void {
610 const target = self.dg.getTarget();
613 fn lower(self: *@This(), ty: Type, arg_val: Value) !void {
611614 const dg = self.dg;
615 const mod = dg.module;
616
617 var val = arg_val;
618 switch (mod.intern_pool.indexToKey(val.toIntern())) {
619 .runtime_value => |rt| val = rt.val.toValue(),
620 else => {},
621 }
612622
613 if (val.isUndef()) {
614 const size = ty.abiSize(target);
623 if (val.isUndefDeep(mod)) {
624 const size = ty.abiSize(mod);
615625 return try self.addUndef(size);
616626 }
617627
618 switch (ty.zigTypeTag()) {
619 .Int => try self.addInt(ty, val),
620 .Float => try self.addFloat(ty, val),
621 .Bool => try self.addConstBool(val.toBool()),
622 .Array => switch (val.tag()) {
623 .aggregate => {
624 const elem_vals = val.castTag(.aggregate).?.data;
625 const elem_ty = ty.elemType();
626 const len = @intCast(u32, ty.arrayLenIncludingSentinel()); // TODO: limit spir-v to 32 bit arrays in a more elegant way.
627 for (elem_vals[0..len]) |elem_val| {
628 try self.lower(elem_ty, elem_val);
629 }
630 },
631 .repeated => {
632 const elem_val = val.castTag(.repeated).?.data;
633 const elem_ty = ty.elemType();
634 const len = @intCast(u32, ty.arrayLen());
635 for (0..len) |_| {
636 try self.lower(elem_ty, elem_val);
637 }
638 if (ty.sentinel()) |sentinel| {
639 try self.lower(elem_ty, sentinel);
640 }
641 },
642 .str_lit => {
643 const str_lit = val.castTag(.str_lit).?.data;
644 const bytes = dg.module.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
645 try self.addBytes(bytes);
646 if (ty.sentinel()) |sentinel| {
647 try self.addByte(@intCast(u8, sentinel.toUnsignedInt(target)));
648 }
649 },
650 .bytes => {
651 const bytes = val.castTag(.bytes).?.data;
652 try self.addBytes(bytes);
653 },
654 else => |tag| return dg.todo("indirect array constant with tag {s}", .{@tagName(tag)}),
628 switch (mod.intern_pool.indexToKey(val.toIntern())) {
629 .int_type,
630 .ptr_type,
631 .array_type,
632 .vector_type,
633 .opt_type,
634 .anyframe_type,
635 .error_union_type,
636 .simple_type,
637 .struct_type,
638 .anon_struct_type,
639 .union_type,
640 .opaque_type,
641 .enum_type,
642 .func_type,
643 .error_set_type,
644 .inferred_error_set_type,
645 => unreachable, // types, not values
646
647 .undef, .runtime_value => unreachable, // handled above
648 .simple_value => |simple_value| switch (simple_value) {
649 .undefined,
650 .void,
651 .null,
652 .empty_struct,
653 .@"unreachable",
654 .generic_poison,
655 => unreachable, // non-runtime values
656 .false, .true => try self.addConstBool(val.toBool()),
655657 },
656 .Pointer => switch (val.tag()) {
657 .decl_ref_mut => {
658 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
659 try self.addDeclRef(ty, decl_index);
660 },
661 .decl_ref => {
662 const decl_index = val.castTag(.decl_ref).?.data;
663 try self.addDeclRef(ty, decl_index);
664 },
665 .slice => {
666 const slice = val.castTag(.slice).?.data;
658 .variable,
659 .extern_func,
660 .func,
661 .enum_literal,
662 .empty_enum_value,
663 => unreachable, // non-runtime values
664 .int => try self.addInt(ty, val),
665 .err => |err| {
666 const int = try mod.getErrorValue(err.name);
667 try self.addConstInt(u16, @intCast(u16, int));
668 },
669 .error_union => |error_union| {
670 const payload_ty = ty.errorUnionPayload(mod);
671 const is_pl = val.errorUnionIsPayload(mod);
672 const error_val = if (!is_pl) val else try mod.intValue(Type.anyerror, 0);
667673
668 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
669 const ptr_ty = ty.slicePtrFieldType(&buf);
674 const eu_layout = dg.errorUnionLayout(payload_ty);
675 if (!eu_layout.payload_has_bits) {
676 return try self.lower(Type.anyerror, error_val);
677 }
670678
671 try self.lower(ptr_ty, slice.ptr);
672 try self.addInt(Type.usize, slice.len);
673 },
674 .null_value, .zero => try self.addNullPtr(try dg.resolveType(ty, .indirect)),
675 .int_u64, .one, .int_big_positive, .lazy_align, .lazy_size => {
676 try self.addInt(Type.usize, val);
677 },
678 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
679 },
680 .Struct => {
681 if (ty.isSimpleTupleOrAnonStruct()) {
682 unreachable; // TODO
679 const payload_size = payload_ty.abiSize(mod);
680 const error_size = Type.anyerror.abiAlignment(mod);
681 const ty_size = ty.abiSize(mod);
682 const padding = ty_size - payload_size - error_size;
683
684 const payload_val = switch (error_union.val) {
685 .err_name => try mod.intern(.{ .undef = payload_ty.ip_index }),
686 .payload => |payload| payload,
687 }.toValue();
688
689 if (eu_layout.error_first) {
690 try self.lower(Type.anyerror, error_val);
691 try self.lower(payload_ty, payload_val);
683692 } else {
684 const struct_ty = ty.castTag(.@"struct").?.data;
693 try self.lower(payload_ty, payload_val);
694 try self.lower(Type.anyerror, error_val);
695 }
685696
686 if (struct_ty.layout == .Packed) {
687 return dg.todo("packed struct constants", .{});
688 }
697 try self.addUndef(padding);
698 },
699 .enum_tag => {
700 const int_val = try val.enumToInt(ty, mod);
689701
690 const struct_begin = self.size;
691 const field_vals = val.castTag(.aggregate).?.data;
692 for (struct_ty.fields.values(), 0..) |field, i| {
693 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
694 try self.lower(field.ty, field_vals[i]);
702 const int_ty = ty.intTagType(mod);
695703
696 // Add padding if required.
697 // TODO: Add to type generation as well?
698 const unpadded_field_end = self.size - struct_begin;
699 const padded_field_end = ty.structFieldOffset(i + 1, target);
700 const padding = padded_field_end - unpadded_field_end;
701 try self.addUndef(padding);
702 }
704 try self.lower(int_ty, int_val);
705 },
706 .float => try self.addFloat(ty, val),
707 .ptr => |ptr| {
708 switch (ptr.addr) {
709 .decl => |decl| try self.addDeclRef(ty, decl),
710 .mut_decl => |mut_decl| try self.addDeclRef(ty, mut_decl.decl),
711 else => |tag| return dg.todo("pointer value of type {s}", .{@tagName(tag)}),
712 }
713 if (ptr.len != .none) {
714 try self.addInt(Type.usize, ptr.len.toValue());
703715 }
704716 },
705 .Optional => {
706 var opt_buf: Type.Payload.ElemType = undefined;
707 const payload_ty = ty.optionalChild(&opt_buf);
708 const has_payload = !val.isNull();
709 const abi_size = ty.abiSize(target);
710
711 if (!payload_ty.hasRuntimeBits()) {
712 try self.addConstBool(has_payload);
717 .opt => {
718 const payload_ty = ty.optionalChild(mod);
719 const payload_val = val.optionalValue(mod);
720 const abi_size = ty.abiSize(mod);
721
722 if (!payload_ty.hasRuntimeBits(mod)) {
723 try self.addConstBool(payload_val != null);
713724 return;
714 } else if (ty.optionalReprIsPayload()) {
725 } else if (ty.optionalReprIsPayload(mod)) {
715726 // Optional representation is a nullable pointer or slice.
716 if (val.castTag(.opt_payload)) |payload| {
717 try self.lower(payload_ty, payload.data);
718 } else if (has_payload) {
719 try self.lower(payload_ty, val);
727 if (payload_val) |pl_val| {
728 try self.lower(payload_ty, pl_val);
720729 } else {
721730 const ptr_ty_ref = try dg.resolveType(ty, .indirect);
722731 try self.addNullPtr(ptr_ty_ref);
......@@ -729,102 +738,98 @@ pub const DeclGen = struct {
729738
730739 // Subtract 1 for @sizeOf(bool).
731740 // TODO: Make this not hardcoded.
732 const payload_size = payload_ty.abiSize(target);
741 const payload_size = payload_ty.abiSize(mod);
733742 const padding = abi_size - payload_size - 1;
734743
735 if (val.castTag(.opt_payload)) |payload| {
736 try self.lower(payload_ty, payload.data);
744 if (payload_val) |pl_val| {
745 try self.lower(payload_ty, pl_val);
737746 } else {
738747 try self.addUndef(payload_size);
739748 }
740 try self.addConstBool(has_payload);
749 try self.addConstBool(payload_val != null);
741750 try self.addUndef(padding);
742751 },
743 .Enum => {
744 var int_val_buffer: Value.Payload.U64 = undefined;
745 const int_val = val.enumToInt(ty, &int_val_buffer);
752 .aggregate => |aggregate| switch (mod.intern_pool.indexToKey(ty.ip_index)) {
753 .array_type => |array_type| {
754 const elem_ty = array_type.child.toType();
755 switch (aggregate.storage) {
756 .bytes => |bytes| try self.addBytes(bytes),
757 .elems, .repeated_elem => {
758 for (0..array_type.len) |i| {
759 try self.lower(elem_ty, switch (aggregate.storage) {
760 .bytes => unreachable,
761 .elems => |elem_vals| elem_vals[@intCast(usize, i)].toValue(),
762 .repeated_elem => |elem_val| elem_val.toValue(),
763 });
764 }
765 },
766 }
767 if (array_type.sentinel != .none) {
768 try self.lower(elem_ty, array_type.sentinel.toValue());
769 }
770 },
771 .vector_type => return dg.todo("indirect constant of type {}", .{ty.fmt(mod)}),
772 .struct_type => {
773 const struct_ty = mod.typeToStruct(ty).?;
746774
747 var int_ty_buffer: Type.Payload.Bits = undefined;
748 const int_ty = ty.intTagType(&int_ty_buffer);
775 if (struct_ty.layout == .Packed) {
776 return dg.todo("packed struct constants", .{});
777 }
749778
750 try self.lower(int_ty, int_val);
779 const struct_begin = self.size;
780 const field_vals = val.castTag(.aggregate).?.data;
781 for (struct_ty.fields.values(), 0..) |field, i| {
782 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
783 try self.lower(field.ty, field_vals[i]);
784
785 // Add padding if required.
786 // TODO: Add to type generation as well?
787 const unpadded_field_end = self.size - struct_begin;
788 const padded_field_end = ty.structFieldOffset(i + 1, mod);
789 const padding = padded_field_end - unpadded_field_end;
790 try self.addUndef(padding);
791 }
792 },
793 .anon_struct_type => unreachable, // TODO
794 else => unreachable,
751795 },
752 .Union => {
753 const tag_and_val = val.castTag(.@"union").?.data;
754 const layout = ty.unionGetLayout(target);
796 .un => |un| {
797 const layout = ty.unionGetLayout(mod);
755798
756799 if (layout.payload_size == 0) {
757 return try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag);
800 return try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
758801 }
759802
760 const union_ty = ty.cast(Type.Payload.Union).?.data;
803 const union_ty = mod.typeToUnion(ty).?;
761804 if (union_ty.layout == .Packed) {
762805 return dg.todo("packed union constants", .{});
763806 }
764807
765 const active_field = ty.unionTagFieldIndex(tag_and_val.tag, dg.module).?;
808 const active_field = ty.unionTagFieldIndex(un.tag.toValue(), dg.module).?;
766809 const active_field_ty = union_ty.fields.values()[active_field].ty;
767810
768811 const has_tag = layout.tag_size != 0;
769812 const tag_first = layout.tag_align >= layout.payload_align;
770813
771814 if (has_tag and tag_first) {
772 try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag);
815 try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
773816 }
774817
775 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime()) blk: {
776 try self.lower(active_field_ty, tag_and_val.val);
777 break :blk active_field_ty.abiSize(target);
818 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {
819 try self.lower(active_field_ty, un.val.toValue());
820 break :blk active_field_ty.abiSize(mod);
778821 } else 0;
779822
780823 const payload_padding_len = layout.payload_size - active_field_size;
781824 try self.addUndef(payload_padding_len);
782825
783826 if (has_tag and !tag_first) {
784 try self.lower(ty.unionTagTypeSafety().?, tag_and_val.tag);
827 try self.lower(ty.unionTagTypeSafety(mod).?, un.tag.toValue());
785828 }
786829
787830 try self.addUndef(layout.padding);
788831 },
789 .ErrorSet => switch (val.tag()) {
790 .@"error" => {
791 const err_name = val.castTag(.@"error").?.data.name;
792 const kv = try dg.module.getErrorValue(err_name);
793 try self.addConstInt(u16, @intCast(u16, kv.value));
794 },
795 .zero => {
796 // Unactivated error set.
797 try self.addConstInt(u16, 0);
798 },
799 else => unreachable,
800 },
801 .ErrorUnion => {
802 const payload_ty = ty.errorUnionPayload();
803 const is_pl = val.errorUnionIsPayload();
804 const error_val = if (!is_pl) val else Value.initTag(.zero);
805
806 const eu_layout = dg.errorUnionLayout(payload_ty);
807 if (!eu_layout.payload_has_bits) {
808 return try self.lower(Type.anyerror, error_val);
809 }
810
811 const payload_size = payload_ty.abiSize(target);
812 const error_size = Type.anyerror.abiAlignment(target);
813 const ty_size = ty.abiSize(target);
814 const padding = ty_size - payload_size - error_size;
815 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
816
817 if (eu_layout.error_first) {
818 try self.lower(Type.anyerror, error_val);
819 try self.lower(payload_ty, payload_val);
820 } else {
821 try self.lower(payload_ty, payload_val);
822 try self.lower(Type.anyerror, error_val);
823 }
824
825 try self.addUndef(padding);
826 },
827 else => |tag| return dg.todo("indirect constant of type {s}", .{@tagName(tag)}),
832 .memoized_call => unreachable,
828833 }
829834 }
830835 };
......@@ -878,7 +883,7 @@ pub const DeclGen = struct {
878883 // const target = self.getTarget();
879884
880885 // TODO: Fix the resulting global linking for these paths.
881 // if (val.isUndef()) {
886 // if (val.isUndef(mod)) {
882887 // // Special case: the entire value is undefined. In this case, we can just
883888 // // generate an OpVariable with no initializer.
884889 // return try section.emit(self.spv.gpa, .OpVariable, .{
......@@ -886,7 +891,7 @@ pub const DeclGen = struct {
886891 // .id_result = result_id,
887892 // .storage_class = storage_class,
888893 // });
889 // } else if (ty.abiSize(target) == 0) {
894 // } else if (ty.abiSize(mod) == 0) {
890895 // // Special case: if the type has no size, then return an undefined pointer.
891896 // return try section.emit(self.spv.gpa, .OpUndef, .{
892897 // .id_result_type = self.typeId(ptr_ty_ref),
......@@ -968,68 +973,25 @@ pub const DeclGen = struct {
968973 /// is then loaded using OpLoad. Such values are loaded into the UniformConstant storage class by default.
969974 /// This function should only be called during function code generation.
970975 fn constant(self: *DeclGen, ty: Type, val: Value, repr: Repr) !IdRef {
971 const target = self.getTarget();
976 const mod = self.module;
972977 const result_ty_ref = try self.resolveType(ty, repr);
973978
974979 log.debug("constant: ty = {}, val = {}", .{ ty.fmt(self.module), val.fmtValue(ty, self.module) });
975980
976 if (val.isUndef()) {
981 if (val.isUndef(mod)) {
977982 return self.spv.constUndef(result_ty_ref);
978983 }
979984
980 switch (ty.zigTypeTag()) {
985 switch (ty.zigTypeTag(mod)) {
981986 .Int => {
982 if (ty.isSignedInt()) {
983 return try self.spv.constInt(result_ty_ref, val.toSignedInt(target));
987 if (ty.isSignedInt(mod)) {
988 return try self.spv.constInt(result_ty_ref, val.toSignedInt(mod));
984989 } else {
985 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(target));
990 return try self.spv.constInt(result_ty_ref, val.toUnsignedInt(mod));
986991 }
987992 },
988 .Bool => switch (repr) {
989 .direct => return try self.spv.constBool(result_ty_ref, val.toBool()),
990 .indirect => return try self.spv.constInt(result_ty_ref, @boolToInt(val.toBool())),
991 },
992 .Float => return switch (ty.floatBits(target)) {
993 16 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float16 = val.toFloat(f16) } } }),
994 32 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float32 = val.toFloat(f32) } } }),
995 64 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float64 = val.toFloat(f64) } } }),
996 80, 128 => unreachable, // TODO
997 else => unreachable,
998 },
999 .ErrorSet => {
1000 const value = switch (val.tag()) {
1001 .@"error" => blk: {
1002 const err_name = val.castTag(.@"error").?.data.name;
1003 const kv = try self.module.getErrorValue(err_name);
1004 break :blk @intCast(u16, kv.value);
1005 },
1006 .zero => 0,
1007 else => unreachable,
1008 };
1009
1010 return try self.spv.constInt(result_ty_ref, value);
1011 },
1012 .ErrorUnion => {
1013 const payload_ty = ty.errorUnionPayload();
1014 const is_pl = val.errorUnionIsPayload();
1015 const error_val = if (!is_pl) val else Value.initTag(.zero);
1016
1017 const eu_layout = self.errorUnionLayout(payload_ty);
1018 if (!eu_layout.payload_has_bits) {
1019 return try self.constant(Type.anyerror, error_val, repr);
1020 }
1021
1022 const payload_val = if (val.castTag(.eu_payload)) |pl| pl.data else Value.initTag(.undef);
1023
1024 var members: [2]IdRef = undefined;
1025 if (eu_layout.error_first) {
1026 members[0] = try self.constant(Type.anyerror, error_val, .indirect);
1027 members[1] = try self.constant(payload_ty, payload_val, .indirect);
1028 } else {
1029 members[0] = try self.constant(payload_ty, payload_val, .indirect);
1030 members[1] = try self.constant(Type.anyerror, error_val, .indirect);
1031 }
1032 return try self.spv.constComposite(result_ty_ref, &members);
993 .Bool => {
994 @compileError("TODO merge conflict failure");
1033995 },
1034996 // TODO: We can handle most pointers here (decl refs etc), because now they emit an extra
1035997 // OpVariable that is not really required.
......@@ -1037,7 +999,7 @@ pub const DeclGen = struct {
1037999 // The value cannot be generated directly, so generate it as an indirect constant,
10381000 // and then perform an OpLoad.
10391001 const result_id = self.spv.allocId();
1040 const alignment = ty.abiAlignment(target);
1002 const alignment = ty.abiAlignment(mod);
10411003 const spv_decl_index = try self.spv.allocDecl(.global);
10421004
10431005 try self.lowerIndirectConstant(
......@@ -1114,9 +1076,9 @@ pub const DeclGen = struct {
11141076 /// NOTE: When the active field is set to something other than the most aligned field, the
11151077 /// resulting struct will be *underaligned*.
11161078 fn resolveUnionType(self: *DeclGen, ty: Type, maybe_active_field: ?usize) !CacheRef {
1117 const target = self.getTarget();
1118 const layout = ty.unionGetLayout(target);
1119 const union_ty = ty.cast(Type.Payload.Union).?.data;
1079 const mod = self.module;
1080 const layout = ty.unionGetLayout(mod);
1081 const union_ty = mod.typeToUnion(ty).?;
11201082
11211083 if (union_ty.layout == .Packed) {
11221084 return self.todo("packed union types", .{});
......@@ -1143,11 +1105,11 @@ pub const DeclGen = struct {
11431105 const active_field = maybe_active_field orelse layout.most_aligned_field;
11441106 const active_field_ty = union_ty.fields.values()[active_field].ty;
11451107
1146 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime()) blk: {
1108 const active_field_size = if (active_field_ty.hasRuntimeBitsIgnoreComptime(mod)) blk: {
11471109 const active_payload_ty_ref = try self.resolveType(active_field_ty, .indirect);
11481110 member_types.appendAssumeCapacity(active_payload_ty_ref);
11491111 member_names.appendAssumeCapacity(try self.spv.resolveString("payload"));
1150 break :blk active_field_ty.abiSize(target);
1112 break :blk active_field_ty.abiSize(mod);
11511113 } else 0;
11521114
11531115 const payload_padding_len = layout.payload_size - active_field_size;
......@@ -1177,21 +1139,21 @@ pub const DeclGen = struct {
11771139
11781140 /// Turn a Zig type into a SPIR-V Type, and return a reference to it.
11791141 fn resolveType(self: *DeclGen, ty: Type, repr: Repr) Error!CacheRef {
1142 const mod = self.module;
11801143 log.debug("resolveType: ty = {}", .{ty.fmt(self.module)});
11811144 const target = self.getTarget();
1182 switch (ty.zigTypeTag()) {
1145 switch (ty.zigTypeTag(mod)) {
11831146 .Void, .NoReturn => return try self.spv.resolve(.void_type),
11841147 .Bool => switch (repr) {
11851148 .direct => return try self.spv.resolve(.bool_type),
11861149 .indirect => return try self.intType(.unsigned, 1),
11871150 },
11881151 .Int => {
1189 const int_info = ty.intInfo(target);
1152 const int_info = ty.intInfo(mod);
11901153 return try self.intType(int_info.signedness, int_info.bits);
11911154 },
11921155 .Enum => {
1193 var buffer: Type.Payload.Bits = undefined;
1194 const tag_ty = ty.intTagType(&buffer);
1156 const tag_ty = ty.intTagType(mod);
11951157 return self.resolveType(tag_ty, repr);
11961158 },
11971159 .Float => {
......@@ -1213,17 +1175,18 @@ pub const DeclGen = struct {
12131175 return try self.spv.resolve(.{ .float_type = .{ .bits = bits } });
12141176 },
12151177 .Array => {
1216 const elem_ty = ty.childType();
1178 const elem_ty = ty.childType(mod);
12171179 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
1218 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel()) orelse {
1219 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel()});
1180 const total_len = std.math.cast(u32, ty.arrayLenIncludingSentinel(mod)) orelse {
1181 return self.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(mod)});
12201182 };
12211183 return self.spv.arrayType(total_len, elem_ty_ref);
12221184 },
12231185 .Fn => switch (repr) {
12241186 .direct => {
1187 const fn_info = mod.typeToFunc(ty).?;
12251188 // TODO: Put this somewhere in Sema.zig
1226 if (ty.fnIsVarArgs())
1189 if (fn_info.is_var_args)
12271190 return self.fail("VarArgs functions are unsupported for SPIR-V", .{});
12281191
12291192 const param_ty_refs = try self.gpa.alloc(CacheRef, ty.fnParamLen());
......@@ -1245,7 +1208,7 @@ pub const DeclGen = struct {
12451208 },
12461209 },
12471210 .Pointer => {
1248 const ptr_info = ty.ptrInfo().data;
1211 const ptr_info = ty.ptrInfo(mod);
12491212
12501213 const storage_class = spvStorageClass(ptr_info.@"addrspace");
12511214 const child_ty_ref = try self.resolveType(ptr_info.pointee_type, .indirect);
......@@ -1277,8 +1240,8 @@ pub const DeclGen = struct {
12771240 // TODO: Properly verify sizes and child type.
12781241
12791242 return try self.spv.resolve(.{ .vector_type = .{
1280 .component_type = try self.resolveType(ty.elemType(), repr),
1281 .component_count = @intCast(u32, ty.vectorLen()),
1243 .component_type = try self.resolveType(ty.childType(mod), repr),
1244 .component_count = @intCast(u32, ty.vectorLen(mod)),
12821245 } });
12831246 },
12841247 .Struct => {
......@@ -1290,7 +1253,7 @@ pub const DeclGen = struct {
12901253 var member_index: usize = 0;
12911254 for (tuple.types, 0..) |field_ty, i| {
12921255 const field_val = tuple.values[i];
1293 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) continue;
1256 if (field_val.ip_index != .unreachable_value or !field_ty.hasRuntimeBits(mod)) continue;
12941257
12951258 member_types[member_index] = try self.resolveType(field_ty, .indirect);
12961259 member_index += 1;
......@@ -1301,7 +1264,7 @@ pub const DeclGen = struct {
13011264 } });
13021265 }
13031266
1304 const struct_ty = ty.castTag(.@"struct").?.data;
1267 const struct_ty = mod.typeToStruct(ty).?;
13051268
13061269 if (struct_ty.layout == .Packed) {
13071270 return try self.resolveType(struct_ty.backing_int_ty, .direct);
......@@ -1314,16 +1277,16 @@ pub const DeclGen = struct {
13141277 defer self.gpa.free(member_names);
13151278
13161279 var member_index: usize = 0;
1317 for (struct_ty.fields.values(), 0..) |field, i| {
1318 if (field.is_comptime or !field.ty.hasRuntimeBits()) continue;
1280 const struct_obj = void; // TODO
1281 for (struct_obj.fields.values(), 0..) |field, i| {
1282 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) continue;
13191283
13201284 member_types[member_index] = try self.resolveType(field.ty, .indirect);
13211285 member_names[member_index] = try self.spv.resolveString(struct_ty.fields.keys()[i]);
13221286 member_index += 1;
13231287 }
13241288
1325 const name = try struct_ty.getFullyQualifiedName(self.module);
1326 defer self.module.gpa.free(name);
1289 const name = mod.intern_pool.stringToSlice(try struct_obj.getFullyQualifiedName(self.module));
13271290
13281291 return try self.spv.resolve(.{ .struct_type = .{
13291292 .name = try self.spv.resolveString(name),
......@@ -1332,9 +1295,8 @@ pub const DeclGen = struct {
13321295 } });
13331296 },
13341297 .Optional => {
1335 var buf: Type.Payload.ElemType = undefined;
1336 const payload_ty = ty.optionalChild(&buf);
1337 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1298 const payload_ty = ty.optionalChild(mod);
1299 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
13381300 // Just use a bool.
13391301 // Note: Always generate the bool with indirect format, to save on some sanity
13401302 // Perform the conversion to a direct bool when the field is extracted.
......@@ -1342,7 +1304,7 @@ pub const DeclGen = struct {
13421304 }
13431305
13441306 const payload_ty_ref = try self.resolveType(payload_ty, .indirect);
1345 if (ty.optionalReprIsPayload()) {
1307 if (ty.optionalReprIsPayload(mod)) {
13461308 // Optional is actually a pointer or a slice.
13471309 return payload_ty_ref;
13481310 }
......@@ -1360,7 +1322,7 @@ pub const DeclGen = struct {
13601322 .Union => return try self.resolveUnionType(ty, null),
13611323 .ErrorSet => return try self.intType(.unsigned, 16),
13621324 .ErrorUnion => {
1363 const payload_ty = ty.errorUnionPayload();
1325 const payload_ty = ty.errorUnionPayload(mod);
13641326 const error_ty_ref = try self.resolveType(Type.anyerror, .indirect);
13651327
13661328 const eu_layout = self.errorUnionLayout(payload_ty);
......@@ -1445,14 +1407,14 @@ pub const DeclGen = struct {
14451407 };
14461408
14471409 fn errorUnionLayout(self: *DeclGen, payload_ty: Type) ErrorUnionLayout {
1448 const target = self.getTarget();
1410 const mod = self.module;
14491411
1450 const error_align = Type.anyerror.abiAlignment(target);
1451 const payload_align = payload_ty.abiAlignment(target);
1412 const error_align = Type.anyerror.abiAlignment(mod);
1413 const payload_align = payload_ty.abiAlignment(mod);
14521414
14531415 const error_first = error_align > payload_align;
14541416 return .{
1455 .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(),
1417 .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(mod),
14561418 .error_first = error_first,
14571419 };
14581420 }
......@@ -1529,28 +1491,28 @@ pub const DeclGen = struct {
15291491 }
15301492
15311493 fn genDecl(self: *DeclGen) !void {
1532 const decl = self.module.declPtr(self.decl_index);
1494 if (true) @panic("TODO: update SPIR-V backend for InternPool changes");
1495 const mod = self.module;
1496 const decl = mod.declPtr(self.decl_index);
15331497 const spv_decl_index = try self.resolveDecl(self.decl_index);
15341498
15351499 const decl_id = self.spv.declPtr(spv_decl_index).result_id;
1536 log.debug("genDecl: id = {}, index = {}, name = {s}", .{ decl_id.id, @enumToInt(spv_decl_index), decl.name });
15371500
1538 if (decl.val.castTag(.function)) |_| {
1539 assert(decl.ty.zigTypeTag() == .Fn);
1501 if (decl.val.getFunction(mod)) |_| {
1502 assert(decl.ty.zigTypeTag(mod) == .Fn);
15401503 const prototype_id = try self.resolveTypeId(decl.ty);
15411504 try self.func.prologue.emit(self.spv.gpa, .OpFunction, .{
1542 .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType()),
1505 .id_result_type = try self.resolveTypeId(decl.ty.fnReturnType(mod)),
15431506 .id_result = decl_id,
15441507 .function_control = .{}, // TODO: We can set inline here if the type requires it.
15451508 .function_type = prototype_id,
15461509 });
15471510
1548 const params = decl.ty.fnParamLen();
1549 var i: usize = 0;
1511 const fn_info = mod.typeToFunc(decl.ty).?;
15501512
1551 try self.args.ensureUnusedCapacity(self.gpa, params);
1552 while (i < params) : (i += 1) {
1553 const param_type_id = try self.resolveTypeId(decl.ty.fnParamType(i));
1513 try self.args.ensureUnusedCapacity(self.gpa, fn_info.param_types.len);
1514 for (fn_info.param_types) |param_type| {
1515 const param_type_id = try self.resolveTypeId(param_type.toType());
15541516 const arg_result_id = self.spv.allocId();
15551517 try self.func.prologue.emit(self.spv.gpa, .OpFunctionParameter, .{
15561518 .id_result_type = param_type_id,
......@@ -1576,8 +1538,7 @@ pub const DeclGen = struct {
15761538 try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
15771539 try self.spv.addFunction(spv_decl_index, self.func);
15781540
1579 const fqn = try decl.getFullyQualifiedName(self.module);
1580 defer self.module.gpa.free(fqn);
1541 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(self.module));
15811542
15821543 try self.spv.sections.debug_names.emit(self.gpa, .OpName, .{
15831544 .target = decl_id,
......@@ -1589,12 +1550,12 @@ pub const DeclGen = struct {
15891550 try self.generateTestEntryPoint(fqn, spv_decl_index);
15901551 }
15911552 } else {
1592 const init_val = if (decl.val.castTag(.variable)) |payload|
1593 payload.data.init
1553 const init_val = if (decl.val.getVariable(mod)) |payload|
1554 payload.init.toValue()
15941555 else
15951556 decl.val;
15961557
1597 if (init_val.tag() == .unreachable_value) {
1558 if (init_val.ip_index == .unreachable_value) {
15981559 return self.todo("importing extern variables", .{});
15991560 }
16001561
......@@ -1634,7 +1595,8 @@ pub const DeclGen = struct {
16341595 /// Convert representation from indirect (in memory) to direct (in 'register')
16351596 /// This converts the argument type from resolveType(ty, .indirect) to resolveType(ty, .direct).
16361597 fn convertToDirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {
1637 return switch (ty.zigTypeTag()) {
1598 const mod = self.module;
1599 return switch (ty.zigTypeTag(mod)) {
16381600 .Bool => blk: {
16391601 const direct_bool_ty_ref = try self.resolveType(ty, .direct);
16401602 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);
......@@ -1655,7 +1617,8 @@ pub const DeclGen = struct {
16551617 /// Convert representation from direct (in 'register) to direct (in memory)
16561618 /// This converts the argument type from resolveType(ty, .direct) to resolveType(ty, .indirect).
16571619 fn convertToIndirect(self: *DeclGen, ty: Type, operand_id: IdRef) !IdRef {
1658 return switch (ty.zigTypeTag()) {
1620 const mod = self.module;
1621 return switch (ty.zigTypeTag(mod)) {
16591622 .Bool => blk: {
16601623 const indirect_bool_ty_ref = try self.resolveType(ty, .indirect);
16611624 break :blk self.boolToInt(indirect_bool_ty_ref, operand_id);
......@@ -1679,11 +1642,12 @@ pub const DeclGen = struct {
16791642 }
16801643
16811644 fn load(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef) !IdRef {
1682 const value_ty = ptr_ty.childType();
1645 const mod = self.module;
1646 const value_ty = ptr_ty.childType(mod);
16831647 const indirect_value_ty_ref = try self.resolveType(value_ty, .indirect);
16841648 const result_id = self.spv.allocId();
16851649 const access = spec.MemoryAccess.Extended{
1686 .Volatile = ptr_ty.isVolatilePtr(),
1650 .Volatile = ptr_ty.isVolatilePtr(mod),
16871651 };
16881652 try self.func.body.emit(self.spv.gpa, .OpLoad, .{
16891653 .id_result_type = self.typeId(indirect_value_ty_ref),
......@@ -1695,10 +1659,11 @@ pub const DeclGen = struct {
16951659 }
16961660
16971661 fn store(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, value_id: IdRef) !void {
1698 const value_ty = ptr_ty.childType();
1662 const mod = self.module;
1663 const value_ty = ptr_ty.childType(mod);
16991664 const indirect_value_id = try self.convertToIndirect(value_ty, value_id);
17001665 const access = spec.MemoryAccess.Extended{
1701 .Volatile = ptr_ty.isVolatilePtr(),
1666 .Volatile = ptr_ty.isVolatilePtr(mod),
17021667 };
17031668 try self.func.body.emit(self.spv.gpa, .OpStore, .{
17041669 .pointer = ptr_id,
......@@ -1714,10 +1679,11 @@ pub const DeclGen = struct {
17141679 }
17151680
17161681 fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void {
1682 const mod = self.module;
1683 const ip = &mod.intern_pool;
17171684 // TODO: remove now-redundant isUnused calls from AIR handler functions
1718 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst)) {
1685 if (self.liveness.isUnused(inst) and !self.air.mustLower(inst, ip))
17191686 return;
1720 }
17211687
17221688 const air_tags = self.air.instructions.items(.tag);
17231689 const maybe_result_id: ?IdRef = switch (air_tags[inst]) {
......@@ -1794,8 +1760,6 @@ pub const DeclGen = struct {
17941760 .br => return self.airBr(inst),
17951761 .breakpoint => return,
17961762 .cond_br => return self.airCondBr(inst),
1797 .constant => unreachable,
1798 .const_ty => unreachable,
17991763 .dbg_stmt => return self.airDbgStmt(inst),
18001764 .loop => return self.airLoop(inst),
18011765 .ret => return self.airRet(inst),
......@@ -1841,7 +1805,7 @@ pub const DeclGen = struct {
18411805 const lhs_id = try self.resolve(bin_op.lhs);
18421806 const rhs_id = try self.resolve(bin_op.rhs);
18431807 const result_id = self.spv.allocId();
1844 const result_type_id = try self.resolveTypeId(self.air.typeOfIndex(inst));
1808 const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst));
18451809 try self.func.body.emit(self.spv.gpa, opcode, .{
18461810 .id_result_type = result_type_id,
18471811 .id_result = result_id,
......@@ -1856,7 +1820,7 @@ pub const DeclGen = struct {
18561820 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
18571821 const lhs_id = try self.resolve(bin_op.lhs);
18581822 const rhs_id = try self.resolve(bin_op.rhs);
1859 const result_type_id = try self.resolveTypeId(self.air.typeOfIndex(inst));
1823 const result_type_id = try self.resolveTypeId(self.typeOfIndex(inst));
18601824
18611825 // the shift and the base must be the same type in SPIR-V, but in Zig the shift is a smaller int.
18621826 const shift_id = self.spv.allocId();
......@@ -1901,15 +1865,15 @@ pub const DeclGen = struct {
19011865 if (self.liveness.isUnused(inst)) return null;
19021866 // LHS and RHS are guaranteed to have the same type, and AIR guarantees
19031867 // the result to be the same as the LHS and RHS, which matches SPIR-V.
1904 const ty = self.air.typeOfIndex(inst);
1868 const ty = self.typeOfIndex(inst);
19051869 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
19061870 var lhs_id = try self.resolve(bin_op.lhs);
19071871 var rhs_id = try self.resolve(bin_op.rhs);
19081872
19091873 const result_ty_ref = try self.resolveType(ty, .direct);
19101874
1911 assert(self.air.typeOf(bin_op.lhs).eql(ty, self.module));
1912 assert(self.air.typeOf(bin_op.rhs).eql(ty, self.module));
1875 assert(self.typeOf(bin_op.lhs).eql(ty, self.module));
1876 assert(self.typeOf(bin_op.rhs).eql(ty, self.module));
19131877
19141878 // Binary operations are generally applicable to both scalar and vector operations
19151879 // in SPIR-V, but int and float versions of operations require different opcodes.
......@@ -1965,8 +1929,8 @@ pub const DeclGen = struct {
19651929 const lhs = try self.resolve(extra.lhs);
19661930 const rhs = try self.resolve(extra.rhs);
19671931
1968 const operand_ty = self.air.typeOf(extra.lhs);
1969 const result_ty = self.air.typeOfIndex(inst);
1932 const operand_ty = self.typeOf(extra.lhs);
1933 const result_ty = self.typeOfIndex(inst);
19701934
19711935 const info = try self.arithmeticTypeInfo(operand_ty);
19721936 switch (info.class) {
......@@ -2056,15 +2020,16 @@ pub const DeclGen = struct {
20562020 }
20572021
20582022 fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2023 const mod = self.module;
20592024 if (self.liveness.isUnused(inst)) return null;
2060 const ty = self.air.typeOfIndex(inst);
2025 const ty = self.typeOfIndex(inst);
20612026 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
20622027 const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data;
20632028 const a = try self.resolve(extra.a);
20642029 const b = try self.resolve(extra.b);
2065 const mask = self.air.values[extra.mask];
2030 const mask = extra.mask.toValue();
20662031 const mask_len = extra.mask_len;
2067 const a_len = self.air.typeOf(extra.a).vectorLen();
2032 const a_len = self.typeOf(extra.a).vectorLen(mod);
20682033
20692034 const result_id = self.spv.allocId();
20702035 const result_type_id = try self.resolveTypeId(ty);
......@@ -2078,12 +2043,11 @@ pub const DeclGen = struct {
20782043
20792044 var i: usize = 0;
20802045 while (i < mask_len) : (i += 1) {
2081 var buf: Value.ElemValueBuffer = undefined;
2082 const elem = mask.elemValueBuffer(self.module, i, &buf);
2083 if (elem.isUndef()) {
2046 const elem = try mask.elemValue(mod, i);
2047 if (elem.isUndef(mod)) {
20842048 self.func.body.writeOperand(spec.LiteralInteger, 0xFFFF_FFFF);
20852049 } else {
2086 const int = elem.toSignedInt(self.getTarget());
2050 const int = elem.toSignedInt(mod);
20872051 const unsigned = if (int >= 0) @intCast(u32, int) else @intCast(u32, ~int + a_len);
20882052 self.func.body.writeOperand(spec.LiteralInteger, unsigned);
20892053 }
......@@ -2130,9 +2094,10 @@ pub const DeclGen = struct {
21302094 }
21312095
21322096 fn ptrAdd(self: *DeclGen, result_ty: Type, ptr_ty: Type, ptr_id: IdRef, offset_id: IdRef) !IdRef {
2097 const mod = self.module;
21332098 const result_ty_ref = try self.resolveType(result_ty, .direct);
21342099
2135 switch (ptr_ty.ptrSize()) {
2100 switch (ptr_ty.ptrSize(mod)) {
21362101 .One => {
21372102 // Pointer to array
21382103 // TODO: Is this correct?
......@@ -2155,8 +2120,8 @@ pub const DeclGen = struct {
21552120 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
21562121 const ptr_id = try self.resolve(bin_op.lhs);
21572122 const offset_id = try self.resolve(bin_op.rhs);
2158 const ptr_ty = self.air.typeOf(bin_op.lhs);
2159 const result_ty = self.air.typeOfIndex(inst);
2123 const ptr_ty = self.typeOf(bin_op.lhs);
2124 const result_ty = self.typeOfIndex(inst);
21602125
21612126 return try self.ptrAdd(result_ty, ptr_ty, ptr_id, offset_id);
21622127 }
......@@ -2166,11 +2131,11 @@ pub const DeclGen = struct {
21662131 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
21672132 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
21682133 const ptr_id = try self.resolve(bin_op.lhs);
2169 const ptr_ty = self.air.typeOf(bin_op.lhs);
2134 const ptr_ty = self.typeOf(bin_op.lhs);
21702135 const offset_id = try self.resolve(bin_op.rhs);
2171 const offset_ty = self.air.typeOf(bin_op.rhs);
2136 const offset_ty = self.typeOf(bin_op.rhs);
21722137 const offset_ty_ref = try self.resolveType(offset_ty, .direct);
2173 const result_ty = self.air.typeOfIndex(inst);
2138 const result_ty = self.typeOfIndex(inst);
21742139
21752140 const negative_offset_id = self.spv.allocId();
21762141 try self.func.body.emit(self.spv.gpa, .OpSNegate, .{
......@@ -2189,13 +2154,13 @@ pub const DeclGen = struct {
21892154 lhs_id: IdRef,
21902155 rhs_id: IdRef,
21912156 ) !IdRef {
2157 const mod = self.module;
21922158 var cmp_lhs_id = lhs_id;
21932159 var cmp_rhs_id = rhs_id;
21942160 const opcode: Opcode = opcode: {
2195 var int_buffer: Type.Payload.Bits = undefined;
2196 const op_ty = switch (ty.zigTypeTag()) {
2161 const op_ty = switch (ty.zigTypeTag(mod)) {
21972162 .Int, .Bool, .Float => ty,
2198 .Enum => ty.intTagType(&int_buffer),
2163 .Enum => ty.intTagType(),
21992164 .ErrorSet => Type.u16,
22002165 .Pointer => blk: {
22012166 // Note that while SPIR-V offers OpPtrEqual and OpPtrNotEqual, they are
......@@ -2291,8 +2256,8 @@ pub const DeclGen = struct {
22912256 const lhs_id = try self.resolve(bin_op.lhs);
22922257 const rhs_id = try self.resolve(bin_op.rhs);
22932258 const bool_ty_id = try self.resolveTypeId(Type.bool);
2294 const ty = self.air.typeOf(bin_op.lhs);
2295 assert(ty.eql(self.air.typeOf(bin_op.rhs), self.module));
2259 const ty = self.typeOf(bin_op.lhs);
2260 assert(ty.eql(self.typeOf(bin_op.rhs), self.module));
22962261
22972262 return try self.cmp(op, bool_ty_id, ty, lhs_id, rhs_id);
22982263 }
......@@ -2303,13 +2268,14 @@ pub const DeclGen = struct {
23032268 src_ty: Type,
23042269 src_id: IdRef,
23052270 ) !IdRef {
2271 const mod = self.module;
23062272 const dst_ty_ref = try self.resolveType(dst_ty, .direct);
23072273 const result_id = self.spv.allocId();
23082274
23092275 // TODO: Some more cases are missing here
23102276 // See fn bitCast in llvm.zig
23112277
2312 if (src_ty.zigTypeTag() == .Int and dst_ty.isPtrAtRuntime()) {
2278 if (src_ty.zigTypeTag(mod) == .Int and dst_ty.isPtrAtRuntime(mod)) {
23132279 try self.func.body.emit(self.spv.gpa, .OpConvertUToPtr, .{
23142280 .id_result_type = self.typeId(dst_ty_ref),
23152281 .id_result = result_id,
......@@ -2329,8 +2295,8 @@ pub const DeclGen = struct {
23292295 if (self.liveness.isUnused(inst)) return null;
23302296 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
23312297 const operand_id = try self.resolve(ty_op.operand);
2332 const operand_ty = self.air.typeOf(ty_op.operand);
2333 const result_ty = self.air.typeOfIndex(inst);
2298 const operand_ty = self.typeOf(ty_op.operand);
2299 const result_ty = self.typeOfIndex(inst);
23342300 return try self.bitCast(result_ty, operand_ty, operand_id);
23352301 }
23362302
......@@ -2339,11 +2305,11 @@ pub const DeclGen = struct {
23392305
23402306 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
23412307 const operand_id = try self.resolve(ty_op.operand);
2342 const dest_ty = self.air.typeOfIndex(inst);
2308 const dest_ty = self.typeOfIndex(inst);
23432309 const dest_ty_id = try self.resolveTypeId(dest_ty);
23442310
2345 const target = self.getTarget();
2346 const dest_info = dest_ty.intInfo(target);
2311 const mod = self.module;
2312 const dest_info = dest_ty.intInfo(mod);
23472313
23482314 // TODO: Masking?
23492315
......@@ -2383,10 +2349,10 @@ pub const DeclGen = struct {
23832349 if (self.liveness.isUnused(inst)) return null;
23842350
23852351 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2386 const operand_ty = self.air.typeOf(ty_op.operand);
2352 const operand_ty = self.typeOf(ty_op.operand);
23872353 const operand_id = try self.resolve(ty_op.operand);
23882354 const operand_info = try self.arithmeticTypeInfo(operand_ty);
2389 const dest_ty = self.air.typeOfIndex(inst);
2355 const dest_ty = self.typeOfIndex(inst);
23902356 const dest_ty_id = try self.resolveTypeId(dest_ty);
23912357
23922358 const result_id = self.spv.allocId();
......@@ -2410,7 +2376,7 @@ pub const DeclGen = struct {
24102376
24112377 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
24122378 const operand_id = try self.resolve(ty_op.operand);
2413 const dest_ty = self.air.typeOfIndex(inst);
2379 const dest_ty = self.typeOfIndex(inst);
24142380 const dest_info = try self.arithmeticTypeInfo(dest_ty);
24152381 const dest_ty_id = try self.resolveTypeId(dest_ty);
24162382
......@@ -2447,20 +2413,21 @@ pub const DeclGen = struct {
24472413 fn airSliceField(self: *DeclGen, inst: Air.Inst.Index, field: u32) !?IdRef {
24482414 if (self.liveness.isUnused(inst)) return null;
24492415 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2450 const field_ty = self.air.typeOfIndex(inst);
2416 const field_ty = self.typeOfIndex(inst);
24512417 const operand_id = try self.resolve(ty_op.operand);
24522418 return try self.extractField(field_ty, operand_id, field);
24532419 }
24542420
24552421 fn airSliceElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2422 const mod = self.module;
24562423 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2457 const slice_ty = self.air.typeOf(bin_op.lhs);
2458 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
2424 const slice_ty = self.typeOf(bin_op.lhs);
2425 if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
24592426
24602427 const slice_id = try self.resolve(bin_op.lhs);
24612428 const index_id = try self.resolve(bin_op.rhs);
24622429
2463 const ptr_ty = self.air.typeOfIndex(inst);
2430 const ptr_ty = self.typeOfIndex(inst);
24642431 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
24652432
24662433 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
......@@ -2468,15 +2435,16 @@ pub const DeclGen = struct {
24682435 }
24692436
24702437 fn airSliceElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2438 const mod = self.module;
24712439 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2472 const slice_ty = self.air.typeOf(bin_op.lhs);
2473 if (!slice_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
2440 const slice_ty = self.typeOf(bin_op.lhs);
2441 if (!slice_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
24742442
24752443 const slice_id = try self.resolve(bin_op.lhs);
24762444 const index_id = try self.resolve(bin_op.rhs);
24772445
24782446 var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2479 const ptr_ty = slice_ty.slicePtrFieldType(&slice_buf);
2447 const ptr_ty = slice_ty.slicePtrFieldType(&slice_buf, mod);
24802448 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
24812449
24822450 const slice_ptr = try self.extractField(ptr_ty, slice_id, 0);
......@@ -2485,11 +2453,12 @@ pub const DeclGen = struct {
24852453 }
24862454
24872455 fn ptrElemPtr(self: *DeclGen, ptr_ty: Type, ptr_id: IdRef, index_id: IdRef) !IdRef {
2456 const mod = self.module;
24882457 // Construct new pointer type for the resulting pointer
2489 const elem_ty = ptr_ty.elemType2(); // use elemType() so that we get T for *[N]T.
2458 const elem_ty = ptr_ty.elemType2(mod); // use elemType() so that we get T for *[N]T.
24902459 const elem_ty_ref = try self.resolveType(elem_ty, .direct);
2491 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace()));
2492 if (ptr_ty.isSinglePointer()) {
2460 const elem_ptr_ty_ref = try self.spv.ptrType(elem_ty_ref, spvStorageClass(ptr_ty.ptrAddressSpace(mod)));
2461 if (ptr_ty.isSinglePointer(mod)) {
24932462 // Pointer-to-array. In this case, the resulting pointer is not of the same type
24942463 // as the ptr_ty (we want a *T, not a *[N]T), and hence we need to use accessChain.
24952464 return try self.accessChain(elem_ptr_ty_ref, ptr_id, &.{index_id});
......@@ -2502,12 +2471,13 @@ pub const DeclGen = struct {
25022471 fn airPtrElemPtr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
25032472 if (self.liveness.isUnused(inst)) return null;
25042473
2474 const mod = self.module;
25052475 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
25062476 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
2507 const ptr_ty = self.air.typeOf(bin_op.lhs);
2508 const elem_ty = ptr_ty.childType();
2477 const ptr_ty = self.typeOf(bin_op.lhs);
2478 const elem_ty = ptr_ty.childType(mod);
25092479 // TODO: Make this return a null ptr or something
2510 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null;
2480 if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
25112481
25122482 const ptr_id = try self.resolve(bin_op.lhs);
25132483 const index_id = try self.resolve(bin_op.rhs);
......@@ -2515,8 +2485,9 @@ pub const DeclGen = struct {
25152485 }
25162486
25172487 fn airPtrElemVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2488 const mod = self.module;
25182489 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2519 const ptr_ty = self.air.typeOf(bin_op.lhs);
2490 const ptr_ty = self.typeOf(bin_op.lhs);
25202491 const ptr_id = try self.resolve(bin_op.lhs);
25212492 const index_id = try self.resolve(bin_op.rhs);
25222493
......@@ -2525,19 +2496,19 @@ pub const DeclGen = struct {
25252496 // If we have a pointer-to-array, construct an element pointer to use with load()
25262497 // If we pass ptr_ty directly, it will attempt to load the entire array rather than
25272498 // just an element.
2528 var elem_ptr_info = ptr_ty.ptrInfo();
2529 elem_ptr_info.data.size = .One;
2530 const elem_ptr_ty = Type.initPayload(&elem_ptr_info.base);
2499 var elem_ptr_info = ptr_ty.ptrInfo(mod);
2500 elem_ptr_info.size = .One;
2501 const elem_ptr_ty = try Type.ptr(undefined, mod, elem_ptr_info);
25312502
25322503 return try self.load(elem_ptr_ty, elem_ptr_id);
25332504 }
25342505
25352506 fn airGetUnionTag(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
25362507 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2537 const un_ty = self.air.typeOf(ty_op.operand);
2508 const un_ty = self.typeOf(ty_op.operand);
25382509
2539 const target = self.module.getTarget();
2540 const layout = un_ty.unionGetLayout(target);
2510 const mod = self.module;
2511 const layout = un_ty.unionGetLayout(mod);
25412512 if (layout.tag_size == 0) return null;
25422513
25432514 const union_handle = try self.resolve(ty_op.operand);
......@@ -2551,17 +2522,18 @@ pub const DeclGen = struct {
25512522 fn airStructFieldVal(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
25522523 if (self.liveness.isUnused(inst)) return null;
25532524
2525 const mod = self.module;
25542526 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
25552527 const struct_field = self.air.extraData(Air.StructField, ty_pl.payload).data;
25562528
2557 const struct_ty = self.air.typeOf(struct_field.struct_operand);
2529 const struct_ty = self.typeOf(struct_field.struct_operand);
25582530 const object_id = try self.resolve(struct_field.struct_operand);
25592531 const field_index = struct_field.field_index;
2560 const field_ty = struct_ty.structFieldType(field_index);
2532 const field_ty = struct_ty.structFieldType(field_index, mod);
25612533
2562 if (!field_ty.hasRuntimeBitsIgnoreComptime()) return null;
2534 if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
25632535
2564 assert(struct_ty.zigTypeTag() == .Struct); // Cannot do unions yet.
2536 assert(struct_ty.zigTypeTag(mod) == .Struct); // Cannot do unions yet.
25652537
25662538 return try self.extractField(field_ty, object_id, field_index);
25672539 }
......@@ -2573,9 +2545,10 @@ pub const DeclGen = struct {
25732545 object_ptr: IdRef,
25742546 field_index: u32,
25752547 ) !?IdRef {
2576 const object_ty = object_ptr_ty.childType();
2577 switch (object_ty.zigTypeTag()) {
2578 .Struct => switch (object_ty.containerLayout()) {
2548 const mod = self.module;
2549 const object_ty = object_ptr_ty.childType(mod);
2550 switch (object_ty.zigTypeTag(mod)) {
2551 .Struct => switch (object_ty.containerLayout(mod)) {
25792552 .Packed => unreachable, // TODO
25802553 else => {
25812554 const field_index_ty_ref = try self.intType(.unsigned, 32);
......@@ -2592,8 +2565,8 @@ pub const DeclGen = struct {
25922565 if (self.liveness.isUnused(inst)) return null;
25932566 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
25942567 const struct_ptr = try self.resolve(ty_op.operand);
2595 const struct_ptr_ty = self.air.typeOf(ty_op.operand);
2596 const result_ptr_ty = self.air.typeOfIndex(inst);
2568 const struct_ptr_ty = self.typeOf(ty_op.operand);
2569 const result_ptr_ty = self.typeOfIndex(inst);
25972570 return try self.structFieldPtr(result_ptr_ty, struct_ptr_ty, struct_ptr, field_index);
25982571 }
25992572
......@@ -2649,9 +2622,10 @@ pub const DeclGen = struct {
26492622
26502623 fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
26512624 if (self.liveness.isUnused(inst)) return null;
2652 const ptr_ty = self.air.typeOfIndex(inst);
2653 assert(ptr_ty.ptrAddressSpace() == .generic);
2654 const child_ty = ptr_ty.childType();
2625 const mod = self.module;
2626 const ptr_ty = self.typeOfIndex(inst);
2627 assert(ptr_ty.ptrAddressSpace(mod) == .generic);
2628 const child_ty = ptr_ty.childType(mod);
26552629 const child_ty_ref = try self.resolveType(child_ty, .indirect);
26562630 return try self.alloc(child_ty_ref, null);
26572631 }
......@@ -2667,6 +2641,7 @@ pub const DeclGen = struct {
26672641 // the current block by first generating the code of the block, then a label, and then generate the rest of the current
26682642 // ir.Block in a different SPIR-V block.
26692643
2644 const mod = self.module;
26702645 const label_id = self.spv.allocId();
26712646
26722647 // 4 chosen as arbitrary initial capacity.
......@@ -2681,7 +2656,7 @@ pub const DeclGen = struct {
26812656 incoming_blocks.deinit(self.gpa);
26822657 }
26832658
2684 const ty = self.air.typeOfIndex(inst);
2659 const ty = self.typeOfIndex(inst);
26852660 const inst_datas = self.air.instructions.items(.data);
26862661 const extra = self.air.extraData(Air.Block, inst_datas[inst].ty_pl.payload);
26872662 const body = self.air.extra[extra.end..][0..extra.data.body_len];
......@@ -2690,7 +2665,7 @@ pub const DeclGen = struct {
26902665 try self.beginSpvBlock(label_id);
26912666
26922667 // If this block didn't produce a value, simply return here.
2693 if (!ty.hasRuntimeBitsIgnoreComptime())
2668 if (!ty.hasRuntimeBitsIgnoreComptime(mod))
26942669 return null;
26952670
26962671 // Combine the result from the blocks using the Phi instruction.
......@@ -2714,9 +2689,10 @@ pub const DeclGen = struct {
27142689 fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void {
27152690 const br = self.air.instructions.items(.data)[inst].br;
27162691 const block = self.blocks.get(br.block_inst).?;
2717 const operand_ty = self.air.typeOf(br.operand);
2692 const operand_ty = self.typeOf(br.operand);
27182693
2719 if (operand_ty.hasRuntimeBits()) {
2694 const mod = self.module;
2695 if (operand_ty.hasRuntimeBits(mod)) {
27202696 const operand_id = try self.resolve(br.operand);
27212697 // current_block_label_id should not be undefined here, lest there is a br or br_void in the function's body.
27222698 try block.incoming_blocks.append(self.gpa, .{ .src_label_id = self.current_block_label_id, .break_value_id = operand_id });
......@@ -2753,7 +2729,10 @@ pub const DeclGen = struct {
27532729
27542730 fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
27552731 const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
2756 const src_fname_id = try self.spv.resolveSourceFileName(self.module.declPtr(self.decl_index));
2732 const src_fname_id = try self.spv.resolveSourceFileName(
2733 self.module,
2734 self.module.declPtr(self.decl_index),
2735 );
27572736 try self.func.body.emit(self.spv.gpa, .OpLine, .{
27582737 .file = src_fname_id,
27592738 .line = dbg_stmt.line,
......@@ -2762,22 +2741,24 @@ pub const DeclGen = struct {
27622741 }
27632742
27642743 fn airLoad(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2744 const mod = self.module;
27652745 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2766 const ptr_ty = self.air.typeOf(ty_op.operand);
2746 const ptr_ty = self.typeOf(ty_op.operand);
27672747 const operand = try self.resolve(ty_op.operand);
2768 if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null;
2748 if (!ptr_ty.isVolatilePtr(mod) and self.liveness.isUnused(inst)) return null;
27692749
27702750 return try self.load(ptr_ty, operand);
27712751 }
27722752
27732753 fn airStore(self: *DeclGen, inst: Air.Inst.Index) !void {
2754 const mod = self.module;
27742755 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2775 const ptr_ty = self.air.typeOf(bin_op.lhs);
2756 const ptr_ty = self.typeOf(bin_op.lhs);
27762757 const ptr = try self.resolve(bin_op.lhs);
27772758 const value = try self.resolve(bin_op.rhs);
27782759 const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
27792760
2780 const val_is_undef = if (self.air.value(bin_op.rhs)) |val| val.isUndefDeep() else false;
2761 const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep(mod) else false;
27812762 if (val_is_undef) {
27822763 const undef = try self.spv.constUndef(ptr_ty_ref);
27832764 try self.store(ptr_ty, ptr, undef);
......@@ -2804,8 +2785,9 @@ pub const DeclGen = struct {
28042785
28052786 fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void {
28062787 const operand = self.air.instructions.items(.data)[inst].un_op;
2807 const operand_ty = self.air.typeOf(operand);
2808 if (operand_ty.hasRuntimeBits()) {
2788 const operand_ty = self.typeOf(operand);
2789 const mod = self.module;
2790 if (operand_ty.hasRuntimeBits(mod)) {
28092791 const operand_id = try self.resolve(operand);
28102792 try self.func.body.emit(self.spv.gpa, .OpReturnValue, .{ .value = operand_id });
28112793 } else {
......@@ -2814,11 +2796,12 @@ pub const DeclGen = struct {
28142796 }
28152797
28162798 fn airRetLoad(self: *DeclGen, inst: Air.Inst.Index) !void {
2799 const mod = self.module;
28172800 const un_op = self.air.instructions.items(.data)[inst].un_op;
2818 const ptr_ty = self.air.typeOf(un_op);
2819 const ret_ty = ptr_ty.childType();
2801 const ptr_ty = self.typeOf(un_op);
2802 const ret_ty = ptr_ty.childType(mod);
28202803
2821 if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
2804 if (!ret_ty.hasRuntimeBitsIgnoreComptime(mod)) {
28222805 try self.func.body.emit(self.spv.gpa, .OpReturn, {});
28232806 return;
28242807 }
......@@ -2831,20 +2814,21 @@ pub const DeclGen = struct {
28312814 }
28322815
28332816 fn airTry(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
2817 const mod = self.module;
28342818 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
28352819 const err_union_id = try self.resolve(pl_op.operand);
28362820 const extra = self.air.extraData(Air.Try, pl_op.payload);
28372821 const body = self.air.extra[extra.end..][0..extra.data.body_len];
28382822
2839 const err_union_ty = self.air.typeOf(pl_op.operand);
2840 const payload_ty = self.air.typeOfIndex(inst);
2823 const err_union_ty = self.typeOf(pl_op.operand);
2824 const payload_ty = self.typeOfIndex(inst);
28412825
28422826 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
28432827 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
28442828
28452829 const eu_layout = self.errorUnionLayout(payload_ty);
28462830
2847 if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) {
2831 if (!err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
28482832 const err_id = if (eu_layout.payload_has_bits)
28492833 try self.extractField(Type.anyerror, err_union_id, eu_layout.errorFieldIndex())
28502834 else
......@@ -2892,17 +2876,18 @@ pub const DeclGen = struct {
28922876 fn airErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
28932877 if (self.liveness.isUnused(inst)) return null;
28942878
2879 const mod = self.module;
28952880 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
28962881 const operand_id = try self.resolve(ty_op.operand);
2897 const err_union_ty = self.air.typeOf(ty_op.operand);
2882 const err_union_ty = self.typeOf(ty_op.operand);
28982883 const err_ty_ref = try self.resolveType(Type.anyerror, .direct);
28992884
2900 if (err_union_ty.errorUnionSet().errorSetIsEmpty()) {
2885 if (err_union_ty.errorUnionSet(mod).errorSetIsEmpty(mod)) {
29012886 // No error possible, so just return undefined.
29022887 return try self.spv.constUndef(err_ty_ref);
29032888 }
29042889
2905 const payload_ty = err_union_ty.errorUnionPayload();
2890 const payload_ty = err_union_ty.errorUnionPayload(mod);
29062891 const eu_layout = self.errorUnionLayout(payload_ty);
29072892
29082893 if (!eu_layout.payload_has_bits) {
......@@ -2916,9 +2901,10 @@ pub const DeclGen = struct {
29162901 fn airWrapErrUnionErr(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
29172902 if (self.liveness.isUnused(inst)) return null;
29182903
2904 const mod = self.module;
29192905 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2920 const err_union_ty = self.air.typeOfIndex(inst);
2921 const payload_ty = err_union_ty.errorUnionPayload();
2906 const err_union_ty = self.typeOfIndex(inst);
2907 const payload_ty = err_union_ty.errorUnionPayload(mod);
29222908 const operand_id = try self.resolve(ty_op.operand);
29232909 const eu_layout = self.errorUnionLayout(payload_ty);
29242910
......@@ -2946,25 +2932,24 @@ pub const DeclGen = struct {
29462932 fn airIsNull(self: *DeclGen, inst: Air.Inst.Index, pred: enum { is_null, is_non_null }) !?IdRef {
29472933 if (self.liveness.isUnused(inst)) return null;
29482934
2935 const mod = self.module;
29492936 const un_op = self.air.instructions.items(.data)[inst].un_op;
29502937 const operand_id = try self.resolve(un_op);
2951 const optional_ty = self.air.typeOf(un_op);
2938 const optional_ty = self.typeOf(un_op);
29522939
2953 var buf: Type.Payload.ElemType = undefined;
2954 const payload_ty = optional_ty.optionalChild(&buf);
2940 const payload_ty = optional_ty.optionalChild(mod);
29552941
29562942 const bool_ty_ref = try self.resolveType(Type.bool, .direct);
29572943
2958 if (optional_ty.optionalReprIsPayload()) {
2944 if (optional_ty.optionalReprIsPayload(mod)) {
29592945 // Pointer payload represents nullability: pointer or slice.
29602946
2961 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2962 const ptr_ty = if (payload_ty.isSlice())
2963 payload_ty.slicePtrFieldType(&ptr_buf)
2947 const ptr_ty = if (payload_ty.isSlice(mod))
2948 payload_ty.slicePtrFieldType(mod)
29642949 else
29652950 payload_ty;
29662951
2967 const ptr_id = if (payload_ty.isSlice())
2952 const ptr_id = if (payload_ty.isSlice(mod))
29682953 try self.extractField(Type.bool, operand_id, 0)
29692954 else
29702955 operand_id;
......@@ -2985,7 +2970,7 @@ pub const DeclGen = struct {
29852970 return result_id;
29862971 }
29872972
2988 const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime())
2973 const is_non_null_id = if (optional_ty.hasRuntimeBitsIgnoreComptime(mod))
29892974 try self.extractField(Type.bool, operand_id, 1)
29902975 else
29912976 // Optional representation is bool indicating whether the optional is set
......@@ -3009,14 +2994,15 @@ pub const DeclGen = struct {
30092994 fn airUnwrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
30102995 if (self.liveness.isUnused(inst)) return null;
30112996
2997 const mod = self.module;
30122998 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
30132999 const operand_id = try self.resolve(ty_op.operand);
3014 const optional_ty = self.air.typeOf(ty_op.operand);
3015 const payload_ty = self.air.typeOfIndex(inst);
3000 const optional_ty = self.typeOf(ty_op.operand);
3001 const payload_ty = self.typeOfIndex(inst);
30163002
3017 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return null;
3003 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return null;
30183004
3019 if (optional_ty.optionalReprIsPayload()) {
3005 if (optional_ty.optionalReprIsPayload(mod)) {
30203006 return operand_id;
30213007 }
30223008
......@@ -3026,16 +3012,17 @@ pub const DeclGen = struct {
30263012 fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
30273013 if (self.liveness.isUnused(inst)) return null;
30283014
3015 const mod = self.module;
30293016 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
3030 const payload_ty = self.air.typeOf(ty_op.operand);
3017 const payload_ty = self.typeOf(ty_op.operand);
30313018
3032 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
3019 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
30333020 return try self.constBool(true, .direct);
30343021 }
30353022
30363023 const operand_id = try self.resolve(ty_op.operand);
3037 const optional_ty = self.air.typeOfIndex(inst);
3038 if (optional_ty.optionalReprIsPayload()) {
3024 const optional_ty = self.typeOfIndex(inst);
3025 if (optional_ty.optionalReprIsPayload(mod)) {
30393026 return operand_id;
30403027 }
30413028
......@@ -3045,30 +3032,29 @@ pub const DeclGen = struct {
30453032 }
30463033
30473034 fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void {
3048 const target = self.getTarget();
3035 const mod = self.module;
30493036 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
30503037 const cond = try self.resolve(pl_op.operand);
3051 const cond_ty = self.air.typeOf(pl_op.operand);
3038 const cond_ty = self.typeOf(pl_op.operand);
30523039 const switch_br = self.air.extraData(Air.SwitchBr, pl_op.payload);
30533040
3054 const cond_words: u32 = switch (cond_ty.zigTypeTag()) {
3041 const cond_words: u32 = switch (cond_ty.zigTypeTag(mod)) {
30553042 .Int => blk: {
3056 const bits = cond_ty.intInfo(target).bits;
3043 const bits = cond_ty.intInfo(mod).bits;
30573044 const backing_bits = self.backingIntBits(bits) orelse {
30583045 return self.todo("implement composite int switch", .{});
30593046 };
30603047 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;
30613048 },
30623049 .Enum => blk: {
3063 var buffer: Type.Payload.Bits = undefined;
3064 const int_ty = cond_ty.intTagType(&buffer);
3065 const int_info = int_ty.intInfo(target);
3050 const int_ty = cond_ty.intTagType(mod);
3051 const int_info = int_ty.intInfo(mod);
30663052 const backing_bits = self.backingIntBits(int_info.bits) orelse {
30673053 return self.todo("implement composite int switch", .{});
30683054 };
30693055 break :blk if (backing_bits <= 32) @as(u32, 1) else 2;
30703056 },
3071 else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag())}), // TODO: Figure out which types apply here, and work around them as we can only do integers.
3057 else => return self.todo("implement switch for type {s}", .{@tagName(cond_ty.zigTypeTag(mod))}), // TODO: Figure out which types apply here, and work around them as we can only do integers.
30723058 };
30733059
30743060 const num_cases = switch_br.data.cases_len;
......@@ -3112,15 +3098,14 @@ pub const DeclGen = struct {
31123098 const label = IdRef{ .id = first_case_label.id + case_i };
31133099
31143100 for (items) |item| {
3115 const value = self.air.value(item) orelse {
3101 const value = (try self.air.value(item, mod)) orelse {
31163102 return self.todo("switch on runtime value???", .{});
31173103 };
3118 const int_val = switch (cond_ty.zigTypeTag()) {
3119 .Int => if (cond_ty.isSignedInt()) @bitCast(u64, value.toSignedInt(target)) else value.toUnsignedInt(target),
3104 const int_val = switch (cond_ty.zigTypeTag(mod)) {
3105 .Int => if (cond_ty.isSignedInt(mod)) @bitCast(u64, value.toSignedInt(mod)) else value.toUnsignedInt(mod),
31203106 .Enum => blk: {
3121 var int_buffer: Value.Payload.U64 = undefined;
31223107 // TODO: figure out of cond_ty is correct (something with enum literals)
3123 break :blk value.enumToInt(cond_ty, &int_buffer).toUnsignedInt(target); // TODO: composite integer constants
3108 break :blk (try value.enumToInt(cond_ty, mod)).toUnsignedInt(mod); // TODO: composite integer constants
31243109 },
31253110 else => unreachable,
31263111 };
......@@ -3164,6 +3149,7 @@ pub const DeclGen = struct {
31643149 }
31653150
31663151 fn airAssembly(self: *DeclGen, inst: Air.Inst.Index) !?IdRef {
3152 const mod = self.module;
31673153 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
31683154 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
31693155
......@@ -3246,7 +3232,7 @@ pub const DeclGen = struct {
32463232 assert(as.errors.items.len != 0);
32473233 assert(self.error_msg == null);
32483234 const loc = LazySrcLoc.nodeOffset(0);
3249 const src_loc = loc.toSrcLoc(self.module.declPtr(self.decl_index));
3235 const src_loc = loc.toSrcLoc(self.module.declPtr(self.decl_index), mod);
32503236 self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
32513237 const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);
32523238
......@@ -3294,19 +3280,20 @@ pub const DeclGen = struct {
32943280 fn airCall(self: *DeclGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !?IdRef {
32953281 _ = modifier;
32963282
3283 const mod = self.module;
32973284 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
32983285 const extra = self.air.extraData(Air.Call, pl_op.payload);
32993286 const args = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
3300 const callee_ty = self.air.typeOf(pl_op.operand);
3301 const zig_fn_ty = switch (callee_ty.zigTypeTag()) {
3287 const callee_ty = self.typeOf(pl_op.operand);
3288 const zig_fn_ty = switch (callee_ty.zigTypeTag(mod)) {
33023289 .Fn => callee_ty,
33033290 .Pointer => return self.fail("cannot call function pointers", .{}),
33043291 else => unreachable,
33053292 };
3306 const fn_info = zig_fn_ty.fnInfo();
3293 const fn_info = mod.typeToFunc(zig_fn_ty).?;
33073294 const return_type = fn_info.return_type;
33083295
3309 const result_type_id = try self.resolveTypeId(return_type);
3296 const result_type_id = try self.resolveTypeId(return_type.toType());
33103297 const result_id = self.spv.allocId();
33113298 const callee_id = try self.resolve(pl_op.operand);
33123299
......@@ -3319,8 +3306,8 @@ pub const DeclGen = struct {
33193306 // before starting to emit OpFunctionCall instructions. Hence the
33203307 // temporary params buffer.
33213308 const arg_id = try self.resolve(arg);
3322 const arg_ty = self.air.typeOf(arg);
3323 if (!arg_ty.hasRuntimeBitsIgnoreComptime()) continue;
3309 const arg_ty = self.typeOf(arg);
3310 if (!arg_ty.hasRuntimeBitsIgnoreComptime(mod)) continue;
33243311
33253312 params[n_params] = arg_id;
33263313 n_params += 1;
......@@ -3333,14 +3320,24 @@ pub const DeclGen = struct {
33333320 .id_ref_3 = params[0..n_params],
33343321 });
33353322
3336 if (return_type.isNoReturn()) {
3323 if (return_type == .noreturn_type) {
33373324 try self.func.body.emit(self.spv.gpa, .OpUnreachable, {});
33383325 }
33393326
3340 if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) {
3327 if (self.liveness.isUnused(inst) or !return_type.toType().hasRuntimeBitsIgnoreComptime(mod)) {
33413328 return null;
33423329 }
33433330
33443331 return result_id;
33453332 }
3333
3334 fn typeOf(self: *DeclGen, inst: Air.Inst.Ref) Type {
3335 const mod = self.module;
3336 return self.air.typeOf(inst, &mod.intern_pool);
3337 }
3338
3339 fn typeOfIndex(self: *DeclGen, inst: Air.Inst.Index) Type {
3340 const mod = self.module;
3341 return self.air.typeOfIndex(inst, &mod.intern_pool);
3342 }
33463343};
src/codegen/spirv/Module.zig+4-3
......@@ -11,7 +11,8 @@ const std = @import("std");
1111const Allocator = std.mem.Allocator;
1212const assert = std.debug.assert;
1313
14const ZigDecl = @import("../../Module.zig").Decl;
14const ZigModule = @import("../../Module.zig");
15const ZigDecl = ZigModule.Decl;
1516
1617const spec = @import("spec.zig");
1718const Word = spec.Word;
......@@ -389,8 +390,8 @@ pub fn addFunction(self: *Module, decl_index: Decl.Index, func: Fn) !void {
389390/// Fetch the result-id of an OpString instruction that encodes the path of the source
390391/// file of the decl. This function may also emit an OpSource with source-level information regarding
391392/// the decl.
392pub fn resolveSourceFileName(self: *Module, decl: *ZigDecl) !IdRef {
393 const path = decl.getFileScope().sub_file_path;
393pub fn resolveSourceFileName(self: *Module, zig_module: *ZigModule, zig_decl: *ZigDecl) !IdRef {
394 const path = zig_decl.getFileScope(zig_module).sub_file_path;
394395 const result = try self.source_file_names.getOrPut(self.gpa, path);
395396 if (!result.found_existing) {
396397 const file_result_id = self.allocId();
src/crash_report.zig+4-4
......@@ -99,7 +99,7 @@ fn dumpStatusReport() !void {
9999 allocator,
100100 anal.body,
101101 anal.body_index,
102 block.namespace.file_scope,
102 mod.namespacePtr(block.namespace).file_scope,
103103 block_src_decl.src_node,
104104 6, // indent
105105 stderr,
......@@ -108,7 +108,7 @@ fn dumpStatusReport() !void {
108108 else => |e| return e,
109109 };
110110 try stderr.writeAll(" For full context, use the command\n zig ast-check -t ");
111 try writeFilePath(block.namespace.file_scope, stderr);
111 try writeFilePath(mod.namespacePtr(block.namespace).file_scope, stderr);
112112 try stderr.writeAll("\n\n");
113113
114114 var parent = anal.parent;
......@@ -121,7 +121,7 @@ fn dumpStatusReport() !void {
121121 print_zir.renderSingleInstruction(
122122 allocator,
123123 curr.body[curr.body_index],
124 curr.block.namespace.file_scope,
124 mod.namespacePtr(curr.block.namespace).file_scope,
125125 curr_block_src_decl.src_node,
126126 6, // indent
127127 stderr,
......@@ -148,7 +148,7 @@ fn writeFilePath(file: *Module.File, stream: anytype) !void {
148148}
149149
150150fn writeFullyQualifiedDeclWithFile(mod: *Module, decl: *Decl, stream: anytype) !void {
151 try writeFilePath(decl.getFileScope(), stream);
151 try writeFilePath(decl.getFileScope(mod), stream);
152152 try stream.writeAll(": ");
153153 try decl.renderFullyQualifiedDebugName(mod, stream);
154154}
src/link.zig+13-24
......@@ -502,8 +502,6 @@ pub const File = struct {
502502 /// of the final binary.
503503 pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: Module.Decl.Index) UpdateDeclError!u32 {
504504 if (build_options.only_c) @compileError("unreachable");
505 const decl = base.options.module.?.declPtr(decl_index);
506 log.debug("lowerUnnamedConst {*} ({s})", .{ decl, decl.name });
507505 switch (base.tag) {
508506 // zig fmt: off
509507 .coff => return @fieldParentPtr(Coff, "base", base).lowerUnnamedConst(tv, decl_index),
......@@ -543,7 +541,6 @@ pub const File = struct {
543541 /// May be called before or after updateDeclExports for any given Decl.
544542 pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {
545543 const decl = module.declPtr(decl_index);
546 log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmt(module) });
547544 assert(decl.has_tv);
548545 if (build_options.only_c) {
549546 assert(base.tag == .c);
......@@ -564,34 +561,27 @@ pub const File = struct {
564561 }
565562
566563 /// May be called before or after updateDeclExports for any given Decl.
567 pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void {
568 const owner_decl = module.declPtr(func.owner_decl);
569 log.debug("updateFunc {*} ({s}), type={}", .{
570 owner_decl, owner_decl.name, owner_decl.ty.fmt(module),
571 });
564 pub fn updateFunc(base: *File, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) UpdateDeclError!void {
572565 if (build_options.only_c) {
573566 assert(base.tag == .c);
574 return @fieldParentPtr(C, "base", base).updateFunc(module, func, air, liveness);
567 return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness);
575568 }
576569 switch (base.tag) {
577570 // zig fmt: off
578 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func, air, liveness),
579 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func, air, liveness),
580 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func, air, liveness),
581 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func, air, liveness),
582 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func, air, liveness),
583 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func, air, liveness),
584 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func, air, liveness),
585 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func, air, liveness),
571 .coff => return @fieldParentPtr(Coff, "base", base).updateFunc(module, func_index, air, liveness),
572 .elf => return @fieldParentPtr(Elf, "base", base).updateFunc(module, func_index, air, liveness),
573 .macho => return @fieldParentPtr(MachO, "base", base).updateFunc(module, func_index, air, liveness),
574 .c => return @fieldParentPtr(C, "base", base).updateFunc(module, func_index, air, liveness),
575 .wasm => return @fieldParentPtr(Wasm, "base", base).updateFunc(module, func_index, air, liveness),
576 .spirv => return @fieldParentPtr(SpirV, "base", base).updateFunc(module, func_index, air, liveness),
577 .plan9 => return @fieldParentPtr(Plan9, "base", base).updateFunc(module, func_index, air, liveness),
578 .nvptx => return @fieldParentPtr(NvPtx, "base", base).updateFunc(module, func_index, air, liveness),
586579 // zig fmt: on
587580 }
588581 }
589582
590583 pub fn updateDeclLineNumber(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void {
591584 const decl = module.declPtr(decl_index);
592 log.debug("updateDeclLineNumber {*} ({s}), line={}", .{
593 decl, decl.name, decl.src_line + 1,
594 });
595585 assert(decl.has_tv);
596586 if (build_options.only_c) {
597587 assert(base.tag == .c);
......@@ -867,7 +857,6 @@ pub const File = struct {
867857 exports: []const *Module.Export,
868858 ) UpdateDeclExportsError!void {
869859 const decl = module.declPtr(decl_index);
870 log.debug("updateDeclExports {*} ({s})", .{ decl, decl.name });
871860 assert(decl.has_tv);
872861 if (build_options.only_c) {
873862 assert(base.tag == .c);
......@@ -1124,13 +1113,13 @@ pub const File = struct {
11241113
11251114 pub fn initDecl(kind: Kind, decl: ?Module.Decl.Index, mod: *Module) LazySymbol {
11261115 return .{ .kind = kind, .ty = if (decl) |decl_index|
1127 mod.declPtr(decl_index).val.castTag(.ty).?.data
1116 mod.declPtr(decl_index).val.toType()
11281117 else
11291118 Type.anyerror };
11301119 }
11311120
1132 pub fn getDecl(self: LazySymbol) Module.Decl.OptionalIndex {
1133 return Module.Decl.OptionalIndex.init(self.ty.getOwnerDeclOrNull());
1121 pub fn getDecl(self: LazySymbol, mod: *Module) Module.Decl.OptionalIndex {
1122 return Module.Decl.OptionalIndex.init(self.ty.getOwnerDeclOrNull(mod));
11341123 }
11351124 };
11361125
src/link/C.zig+10-7
......@@ -6,6 +6,7 @@ const fs = std.fs;
66
77const C = @This();
88const Module = @import("../Module.zig");
9const InternPool = @import("../InternPool.zig");
910const Compilation = @import("../Compilation.zig");
1011const codegen = @import("../codegen/c.zig");
1112const link = @import("../link.zig");
......@@ -87,12 +88,13 @@ pub fn freeDecl(self: *C, decl_index: Module.Decl.Index) void {
8788 }
8889}
8990
90pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
91pub fn updateFunc(self: *C, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
9192 const tracy = trace(@src());
9293 defer tracy.end();
9394
9495 const gpa = self.base.allocator;
9596
97 const func = module.funcPtr(func_index);
9698 const decl_index = func.owner_decl;
9799 const gop = try self.decl_table.getOrPut(gpa, decl_index);
98100 if (!gop.found_existing) {
......@@ -111,7 +113,7 @@ pub fn updateFunc(self: *C, module: *Module, func: *Module.Fn, air: Air, livenes
111113 .value_map = codegen.CValueMap.init(gpa),
112114 .air = air,
113115 .liveness = liveness,
114 .func = func,
116 .func_index = func_index,
115117 .object = .{
116118 .dg = .{
117119 .gpa = gpa,
......@@ -288,11 +290,11 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
288290 }
289291
290292 {
291 var export_names = std.StringHashMapUnmanaged(void){};
293 var export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
292294 defer export_names.deinit(gpa);
293295 try export_names.ensureTotalCapacity(gpa, @intCast(u32, module.decl_exports.entries.len));
294296 for (module.decl_exports.values()) |exports| for (exports.items) |@"export"|
295 try export_names.put(gpa, @"export".options.name, {});
297 try export_names.put(gpa, @"export".opts.name, {});
296298
297299 while (f.remaining_decls.popOrNull()) |kv| {
298300 const decl_index = kv.key;
......@@ -552,10 +554,11 @@ fn flushDecl(
552554 self: *C,
553555 f: *Flush,
554556 decl_index: Module.Decl.Index,
555 export_names: std.StringHashMapUnmanaged(void),
557 export_names: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
556558) FlushDeclError!void {
557559 const gpa = self.base.allocator;
558 const decl = self.base.options.module.?.declPtr(decl_index);
560 const mod = self.base.options.module.?;
561 const decl = mod.declPtr(decl_index);
559562 // Before flushing any particular Decl we must ensure its
560563 // dependencies are already flushed, so that the order in the .c
561564 // file comes out correctly.
......@@ -569,7 +572,7 @@ fn flushDecl(
569572
570573 try self.flushLazyFns(f, decl_block.lazy_fns);
571574 try f.all_buffers.ensureUnusedCapacity(gpa, 1);
572 if (!(decl.isExtern() and export_names.contains(mem.span(decl.name))))
575 if (!(decl.isExtern(mod) and export_names.contains(decl.name)))
573576 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
574577}
575578
src/link/Coff.zig+71-66
......@@ -1032,20 +1032,21 @@ fn freeAtom(self: *Coff, atom_index: Atom.Index) void {
10321032 self.getAtomPtr(atom_index).sym_index = 0;
10331033}
10341034
1035pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1035pub fn updateFunc(self: *Coff, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
10361036 if (build_options.skip_non_native and builtin.object_format != .coff) {
10371037 @panic("Attempted to compile for object format that was disabled by build configuration");
10381038 }
10391039 if (build_options.have_llvm) {
10401040 if (self.llvm_object) |llvm_object| {
1041 return llvm_object.updateFunc(module, func, air, liveness);
1041 return llvm_object.updateFunc(mod, func_index, air, liveness);
10421042 }
10431043 }
10441044 const tracy = trace(@src());
10451045 defer tracy.end();
10461046
1047 const func = mod.funcPtr(func_index);
10471048 const decl_index = func.owner_decl;
1048 const decl = module.declPtr(decl_index);
1049 const decl = mod.declPtr(decl_index);
10491050
10501051 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
10511052 self.freeUnnamedConsts(decl_index);
......@@ -1056,8 +1057,8 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
10561057
10571058 const res = try codegen.generateFunction(
10581059 &self.base,
1059 decl.srcLoc(),
1060 func,
1060 decl.srcLoc(mod),
1061 func_index,
10611062 air,
10621063 liveness,
10631064 &code_buffer,
......@@ -1067,7 +1068,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
10671068 .ok => code_buffer.items,
10681069 .fail => |em| {
10691070 decl.analysis = .codegen_failure;
1070 try module.failed_decls.put(module.gpa, decl_index, em);
1071 try mod.failed_decls.put(mod.gpa, decl_index, em);
10711072 return;
10721073 },
10731074 };
......@@ -1076,7 +1077,7 @@ pub fn updateFunc(self: *Coff, module: *Module, func: *Module.Fn, air: Air, live
10761077
10771078 // Since we updated the vaddr and the size, each corresponding export
10781079 // symbol also needs to be updated.
1079 return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
1080 return self.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
10801081}
10811082
10821083pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
......@@ -1096,8 +1097,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
10961097 const atom_index = try self.createAtom();
10971098
10981099 const sym_name = blk: {
1099 const decl_name = try decl.getFullyQualifiedName(mod);
1100 defer gpa.free(decl_name);
1100 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
11011101
11021102 const index = unnamed_consts.items.len;
11031103 break :blk try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
......@@ -1110,7 +1110,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
11101110 sym.section_number = @intToEnum(coff.SectionNumber, self.rdata_section_index.? + 1);
11111111 }
11121112
1113 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .none, .{
1113 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .none, .{
11141114 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
11151115 });
11161116 var code = switch (res) {
......@@ -1123,7 +1123,7 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
11231123 },
11241124 };
11251125
1126 const required_alignment = tv.ty.abiAlignment(self.base.options.target);
1126 const required_alignment = tv.ty.abiAlignment(mod);
11271127 const atom = self.getAtomPtr(atom_index);
11281128 atom.size = @intCast(u32, code.len);
11291129 atom.getSymbolPtr(self).value = try self.allocateAtom(atom_index, atom.size, required_alignment);
......@@ -1141,25 +1141,24 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: Module.Decl.In
11411141
11421142pub fn updateDecl(
11431143 self: *Coff,
1144 module: *Module,
1144 mod: *Module,
11451145 decl_index: Module.Decl.Index,
11461146) link.File.UpdateDeclError!void {
11471147 if (build_options.skip_non_native and builtin.object_format != .coff) {
11481148 @panic("Attempted to compile for object format that was disabled by build configuration");
11491149 }
11501150 if (build_options.have_llvm) {
1151 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl_index);
1151 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
11521152 }
11531153 const tracy = trace(@src());
11541154 defer tracy.end();
11551155
1156 const decl = module.declPtr(decl_index);
1156 const decl = mod.declPtr(decl_index);
11571157
1158 if (decl.val.tag() == .extern_fn) {
1158 if (decl.val.getExternFunc(mod)) |_| {
11591159 return; // TODO Should we do more when front-end analyzed extern decl?
11601160 }
1161 if (decl.val.castTag(.variable)) |payload| {
1162 const variable = payload.data;
1161 if (decl.val.getVariable(mod)) |variable| {
11631162 if (variable.is_extern) {
11641163 return; // TODO Should we do more when front-end analyzed extern decl?
11651164 }
......@@ -1172,8 +1171,8 @@ pub fn updateDecl(
11721171 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
11731172 defer code_buffer.deinit();
11741173
1175 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
1176 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
1174 const decl_val = if (decl.val.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
1175 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
11771176 .ty = decl.ty,
11781177 .val = decl_val,
11791178 }, &code_buffer, .none, .{
......@@ -1183,7 +1182,7 @@ pub fn updateDecl(
11831182 .ok => code_buffer.items,
11841183 .fail => |em| {
11851184 decl.analysis = .codegen_failure;
1186 try module.failed_decls.put(module.gpa, decl_index, em);
1185 try mod.failed_decls.put(mod.gpa, decl_index, em);
11871186 return;
11881187 },
11891188 };
......@@ -1192,7 +1191,7 @@ pub fn updateDecl(
11921191
11931192 // Since we updated the vaddr and the size, each corresponding export
11941193 // symbol also needs to be updated.
1195 return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
1194 return self.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
11961195}
11971196
11981197fn updateLazySymbolAtom(
......@@ -1217,8 +1216,8 @@ fn updateLazySymbolAtom(
12171216 const atom = self.getAtomPtr(atom_index);
12181217 const local_sym_index = atom.getSymbolIndex().?;
12191218
1220 const src = if (sym.ty.getOwnerDeclOrNull()) |owner_decl|
1221 mod.declPtr(owner_decl).srcLoc()
1219 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
1220 mod.declPtr(owner_decl).srcLoc(mod)
12221221 else
12231222 Module.SrcLoc{
12241223 .file_scope = undefined,
......@@ -1262,7 +1261,8 @@ fn updateLazySymbolAtom(
12621261}
12631262
12641263pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index {
1265 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
1264 const mod = self.base.options.module.?;
1265 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod));
12661266 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
12671267 if (!gop.found_existing) gop.value_ptr.* = .{};
12681268 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
......@@ -1277,7 +1277,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato
12771277 metadata.state.* = .pending_flush;
12781278 const atom = metadata.atom.*;
12791279 // anyerror needs to be deferred until flushModule
1280 if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
1280 if (sym.getDecl(mod) != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
12811281 .code => self.text_section_index.?,
12821282 .const_data => self.rdata_section_index.?,
12831283 });
......@@ -1299,10 +1299,11 @@ pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom.
12991299fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
13001300 const decl = self.base.options.module.?.declPtr(decl_index);
13011301 const ty = decl.ty;
1302 const zig_ty = ty.zigTypeTag();
1302 const mod = self.base.options.module.?;
1303 const zig_ty = ty.zigTypeTag(mod);
13031304 const val = decl.val;
13041305 const index: u16 = blk: {
1305 if (val.isUndefDeep()) {
1306 if (val.isUndefDeep(mod)) {
13061307 // TODO in release-fast and release-small, we should put undef in .bss
13071308 break :blk self.data_section_index.?;
13081309 }
......@@ -1311,7 +1312,7 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
13111312 // TODO: what if this is a function pointer?
13121313 .Fn => break :blk self.text_section_index.?,
13131314 else => {
1314 if (val.castTag(.variable)) |_| {
1315 if (val.getVariable(mod)) |_| {
13151316 break :blk self.data_section_index.?;
13161317 }
13171318 break :blk self.rdata_section_index.?;
......@@ -1322,15 +1323,13 @@ fn getDeclOutputSection(self: *Coff, decl_index: Module.Decl.Index) u16 {
13221323}
13231324
13241325fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []u8, complex_type: coff.ComplexType) !void {
1325 const gpa = self.base.allocator;
13261326 const mod = self.base.options.module.?;
13271327 const decl = mod.declPtr(decl_index);
13281328
1329 const decl_name = try decl.getFullyQualifiedName(mod);
1330 defer gpa.free(decl_name);
1329 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
13311330
13321331 log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });
1333 const required_alignment = decl.getAlignment(self.base.options.target);
1332 const required_alignment = decl.getAlignment(mod);
13341333
13351334 const decl_metadata = self.decls.get(decl_index).?;
13361335 const atom_index = decl_metadata.atom;
......@@ -1410,7 +1409,7 @@ pub fn freeDecl(self: *Coff, decl_index: Module.Decl.Index) void {
14101409
14111410pub fn updateDeclExports(
14121411 self: *Coff,
1413 module: *Module,
1412 mod: *Module,
14141413 decl_index: Module.Decl.Index,
14151414 exports: []const *Module.Export,
14161415) link.File.UpdateDeclExportsError!void {
......@@ -1418,61 +1417,60 @@ pub fn updateDeclExports(
14181417 @panic("Attempted to compile for object format that was disabled by build configuration");
14191418 }
14201419
1420 const ip = &mod.intern_pool;
1421
14211422 if (build_options.have_llvm) {
14221423 // Even in the case of LLVM, we need to notice certain exported symbols in order to
14231424 // detect the default subsystem.
14241425 for (exports) |exp| {
1425 const exported_decl = module.declPtr(exp.exported_decl);
1426 if (exported_decl.getFunction() == null) continue;
1426 const exported_decl = mod.declPtr(exp.exported_decl);
1427 if (exported_decl.getOwnedFunctionIndex(mod) == .none) continue;
14271428 const winapi_cc = switch (self.base.options.target.cpu.arch) {
14281429 .x86 => std.builtin.CallingConvention.Stdcall,
14291430 else => std.builtin.CallingConvention.C,
14301431 };
1431 const decl_cc = exported_decl.ty.fnCallingConvention();
1432 if (decl_cc == .C and mem.eql(u8, exp.options.name, "main") and
1432 const decl_cc = exported_decl.ty.fnCallingConvention(mod);
1433 if (decl_cc == .C and ip.stringEqlSlice(exp.opts.name, "main") and
14331434 self.base.options.link_libc)
14341435 {
1435 module.stage1_flags.have_c_main = true;
1436 mod.stage1_flags.have_c_main = true;
14361437 } else if (decl_cc == winapi_cc and self.base.options.target.os.tag == .windows) {
1437 if (mem.eql(u8, exp.options.name, "WinMain")) {
1438 module.stage1_flags.have_winmain = true;
1439 } else if (mem.eql(u8, exp.options.name, "wWinMain")) {
1440 module.stage1_flags.have_wwinmain = true;
1441 } else if (mem.eql(u8, exp.options.name, "WinMainCRTStartup")) {
1442 module.stage1_flags.have_winmain_crt_startup = true;
1443 } else if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) {
1444 module.stage1_flags.have_wwinmain_crt_startup = true;
1445 } else if (mem.eql(u8, exp.options.name, "DllMainCRTStartup")) {
1446 module.stage1_flags.have_dllmain_crt_startup = true;
1438 if (ip.stringEqlSlice(exp.opts.name, "WinMain")) {
1439 mod.stage1_flags.have_winmain = true;
1440 } else if (ip.stringEqlSlice(exp.opts.name, "wWinMain")) {
1441 mod.stage1_flags.have_wwinmain = true;
1442 } else if (ip.stringEqlSlice(exp.opts.name, "WinMainCRTStartup")) {
1443 mod.stage1_flags.have_winmain_crt_startup = true;
1444 } else if (ip.stringEqlSlice(exp.opts.name, "wWinMainCRTStartup")) {
1445 mod.stage1_flags.have_wwinmain_crt_startup = true;
1446 } else if (ip.stringEqlSlice(exp.opts.name, "DllMainCRTStartup")) {
1447 mod.stage1_flags.have_dllmain_crt_startup = true;
14471448 }
14481449 }
14491450 }
14501451
1451 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports);
1452 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(mod, decl_index, exports);
14521453 }
14531454
1454 const tracy = trace(@src());
1455 defer tracy.end();
1456
14571455 const gpa = self.base.allocator;
14581456
1459 const decl = module.declPtr(decl_index);
1457 const decl = mod.declPtr(decl_index);
14601458 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
14611459 const atom = self.getAtom(atom_index);
14621460 const decl_sym = atom.getSymbol(self);
14631461 const decl_metadata = self.decls.getPtr(decl_index).?;
14641462
14651463 for (exports) |exp| {
1466 log.debug("adding new export '{s}'", .{exp.options.name});
1464 log.debug("adding new export '{}'", .{exp.opts.name.fmt(&mod.intern_pool)});
14671465
1468 if (exp.options.section) |section_name| {
1466 if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section_name| {
14691467 if (!mem.eql(u8, section_name, ".text")) {
1470 try module.failed_exports.putNoClobber(
1471 module.gpa,
1468 try mod.failed_exports.putNoClobber(
1469 gpa,
14721470 exp,
14731471 try Module.ErrorMsg.create(
14741472 gpa,
1475 decl.srcLoc(),
1473 decl.srcLoc(mod),
14761474 "Unimplemented: ExportOptions.section",
14771475 .{},
14781476 ),
......@@ -1481,13 +1479,13 @@ pub fn updateDeclExports(
14811479 }
14821480 }
14831481
1484 if (exp.options.linkage == .LinkOnce) {
1485 try module.failed_exports.putNoClobber(
1486 module.gpa,
1482 if (exp.opts.linkage == .LinkOnce) {
1483 try mod.failed_exports.putNoClobber(
1484 gpa,
14871485 exp,
14881486 try Module.ErrorMsg.create(
14891487 gpa,
1490 decl.srcLoc(),
1488 decl.srcLoc(mod),
14911489 "Unimplemented: GlobalLinkage.LinkOnce",
14921490 .{},
14931491 ),
......@@ -1495,19 +1493,19 @@ pub fn updateDeclExports(
14951493 continue;
14961494 }
14971495
1498 const sym_index = decl_metadata.getExport(self, exp.options.name) orelse blk: {
1496 const sym_index = decl_metadata.getExport(self, mod.intern_pool.stringToSlice(exp.opts.name)) orelse blk: {
14991497 const sym_index = try self.allocateSymbol();
15001498 try decl_metadata.exports.append(gpa, sym_index);
15011499 break :blk sym_index;
15021500 };
15031501 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
15041502 const sym = self.getSymbolPtr(sym_loc);
1505 try self.setSymbolName(sym, exp.options.name);
1503 try self.setSymbolName(sym, mod.intern_pool.stringToSlice(exp.opts.name));
15061504 sym.value = decl_sym.value;
15071505 sym.section_number = @intToEnum(coff.SectionNumber, self.text_section_index.? + 1);
15081506 sym.type = .{ .complex_type = .FUNCTION, .base_type = .NULL };
15091507
1510 switch (exp.options.linkage) {
1508 switch (exp.opts.linkage) {
15111509 .Strong => {
15121510 sym.storage_class = .EXTERNAL;
15131511 },
......@@ -1520,9 +1518,15 @@ pub fn updateDeclExports(
15201518 }
15211519}
15221520
1523pub fn deleteDeclExport(self: *Coff, decl_index: Module.Decl.Index, name: []const u8) void {
1521pub fn deleteDeclExport(
1522 self: *Coff,
1523 decl_index: Module.Decl.Index,
1524 name_ip: InternPool.NullTerminatedString,
1525) void {
15241526 if (self.llvm_object) |_| return;
15251527 const metadata = self.decls.getPtr(decl_index) orelse return;
1528 const mod = self.base.options.module.?;
1529 const name = mod.intern_pool.stringToSlice(name_ip);
15261530 const sym_index = metadata.getExportPtr(self, name) orelse return;
15271531
15281532 const gpa = self.base.allocator;
......@@ -2538,6 +2542,7 @@ const ImportTable = @import("Coff/ImportTable.zig");
25382542const Liveness = @import("../Liveness.zig");
25392543const LlvmObject = @import("../codegen/llvm.zig").Object;
25402544const Module = @import("../Module.zig");
2545const InternPool = @import("../InternPool.zig");
25412546const Object = @import("Coff/Object.zig");
25422547const Relocation = @import("Coff/Relocation.zig");
25432548const TableSection = @import("table_section.zig").TableSection;
src/link/Dwarf.zig+119-136
......@@ -18,6 +18,7 @@ const LinkBlock = File.LinkBlock;
1818const LinkFn = File.LinkFn;
1919const LinkerLoad = @import("../codegen.zig").LinkerLoad;
2020const Module = @import("../Module.zig");
21const InternPool = @import("../InternPool.zig");
2122const StringTable = @import("strtab.zig").StringTable;
2223const Type = @import("../type.zig").Type;
2324const Value = @import("../value.zig").Value;
......@@ -86,12 +87,7 @@ pub const DeclState = struct {
8687 dbg_info: std.ArrayList(u8),
8788 abbrev_type_arena: std.heap.ArenaAllocator,
8889 abbrev_table: std.ArrayListUnmanaged(AbbrevEntry) = .{},
89 abbrev_resolver: std.HashMapUnmanaged(
90 Type,
91 u32,
92 Type.HashContext64,
93 std.hash_map.default_max_load_percentage,
94 ) = .{},
90 abbrev_resolver: std.AutoHashMapUnmanaged(InternPool.Index, u32) = .{},
9591 abbrev_relocs: std.ArrayListUnmanaged(AbbrevRelocation) = .{},
9692 exprloc_relocs: std.ArrayListUnmanaged(ExprlocRelocation) = .{},
9793
......@@ -141,9 +137,7 @@ pub const DeclState = struct {
141137 /// @symbol signifies a type abbreviation posititioned somewhere in the .debug_abbrev section
142138 /// which we use as our target of the relocation.
143139 fn addTypeRelocGlobal(self: *DeclState, atom_index: Atom.Index, ty: Type, offset: u32) !void {
144 const resolv = self.abbrev_resolver.getContext(ty, .{
145 .mod = self.mod,
146 }) orelse blk: {
140 const resolv = self.abbrev_resolver.get(ty.toIntern()) orelse blk: {
147141 const sym_index = @intCast(u32, self.abbrev_table.items.len);
148142 try self.abbrev_table.append(self.gpa, .{
149143 .atom_index = atom_index,
......@@ -151,12 +145,8 @@ pub const DeclState = struct {
151145 .offset = undefined,
152146 });
153147 log.debug("%{d}: {}", .{ sym_index, ty.fmt(self.mod) });
154 try self.abbrev_resolver.putNoClobberContext(self.gpa, ty, sym_index, .{
155 .mod = self.mod,
156 });
157 break :blk self.abbrev_resolver.getContext(ty, .{
158 .mod = self.mod,
159 }).?;
148 try self.abbrev_resolver.putNoClobber(self.gpa, ty.toIntern(), sym_index);
149 break :blk sym_index;
160150 };
161151 log.debug("{x}: %{d} + 0", .{ offset, resolv });
162152 try self.abbrev_relocs.append(self.gpa, .{
......@@ -169,16 +159,16 @@ pub const DeclState = struct {
169159
170160 fn addDbgInfoType(
171161 self: *DeclState,
172 module: *Module,
162 mod: *Module,
173163 atom_index: Atom.Index,
174164 ty: Type,
175165 ) error{OutOfMemory}!void {
176166 const arena = self.abbrev_type_arena.allocator();
177167 const dbg_info_buffer = &self.dbg_info;
178 const target = module.getTarget();
168 const target = mod.getTarget();
179169 const target_endian = target.cpu.arch.endian();
180170
181 switch (ty.zigTypeTag()) {
171 switch (ty.zigTypeTag(mod)) {
182172 .NoReturn => unreachable,
183173 .Void => {
184174 try dbg_info_buffer.append(@enumToInt(AbbrevKind.pad1));
......@@ -189,12 +179,12 @@ pub const DeclState = struct {
189179 // DW.AT.encoding, DW.FORM.data1
190180 dbg_info_buffer.appendAssumeCapacity(DW.ATE.boolean);
191181 // DW.AT.byte_size, DW.FORM.udata
192 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
182 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
193183 // DW.AT.name, DW.FORM.string
194 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
184 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
195185 },
196186 .Int => {
197 const info = ty.intInfo(target);
187 const info = ty.intInfo(mod);
198188 try dbg_info_buffer.ensureUnusedCapacity(12);
199189 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
200190 // DW.AT.encoding, DW.FORM.data1
......@@ -203,31 +193,30 @@ pub const DeclState = struct {
203193 .unsigned => DW.ATE.unsigned,
204194 });
205195 // DW.AT.byte_size, DW.FORM.udata
206 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
196 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
207197 // DW.AT.name, DW.FORM.string
208 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
198 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
209199 },
210200 .Optional => {
211 if (ty.isPtrLikeOptional()) {
201 if (ty.isPtrLikeOptional(mod)) {
212202 try dbg_info_buffer.ensureUnusedCapacity(12);
213203 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.base_type));
214204 // DW.AT.encoding, DW.FORM.data1
215205 dbg_info_buffer.appendAssumeCapacity(DW.ATE.address);
216206 // DW.AT.byte_size, DW.FORM.udata
217 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
207 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
218208 // DW.AT.name, DW.FORM.string
219 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
209 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
220210 } else {
221211 // Non-pointer optionals are structs: struct { .maybe = *, .val = * }
222 var buf = try arena.create(Type.Payload.ElemType);
223 const payload_ty = ty.optionalChild(buf);
212 const payload_ty = ty.optionalChild(mod);
224213 // DW.AT.structure_type
225214 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
226215 // DW.AT.byte_size, DW.FORM.udata
227 const abi_size = ty.abiSize(target);
216 const abi_size = ty.abiSize(mod);
228217 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
229218 // DW.AT.name, DW.FORM.string
230 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
219 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
231220 // DW.AT.member
232221 try dbg_info_buffer.ensureUnusedCapacity(7);
233222 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
......@@ -251,14 +240,14 @@ pub const DeclState = struct {
251240 try dbg_info_buffer.resize(index + 4);
252241 try self.addTypeRelocGlobal(atom_index, payload_ty, @intCast(u32, index));
253242 // DW.AT.data_member_location, DW.FORM.udata
254 const offset = abi_size - payload_ty.abiSize(target);
243 const offset = abi_size - payload_ty.abiSize(mod);
255244 try leb128.writeULEB128(dbg_info_buffer.writer(), offset);
256245 // DW.AT.structure_type delimit children
257246 try dbg_info_buffer.append(0);
258247 }
259248 },
260249 .Pointer => {
261 if (ty.isSlice()) {
250 if (ty.isSlice(mod)) {
262251 // Slices are structs: struct { .ptr = *, .len = N }
263252 const ptr_bits = target.ptrBitWidth();
264253 const ptr_bytes = @intCast(u8, @divExact(ptr_bits, 8));
......@@ -266,9 +255,9 @@ pub const DeclState = struct {
266255 try dbg_info_buffer.ensureUnusedCapacity(2);
267256 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_type));
268257 // DW.AT.byte_size, DW.FORM.udata
269 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
258 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
270259 // DW.AT.name, DW.FORM.string
271 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
260 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
272261 // DW.AT.member
273262 try dbg_info_buffer.ensureUnusedCapacity(5);
274263 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
......@@ -278,8 +267,7 @@ pub const DeclState = struct {
278267 // DW.AT.type, DW.FORM.ref4
279268 var index = dbg_info_buffer.items.len;
280269 try dbg_info_buffer.resize(index + 4);
281 var buf = try arena.create(Type.SlicePtrFieldTypeBuffer);
282 const ptr_ty = ty.slicePtrFieldType(buf);
270 const ptr_ty = ty.slicePtrFieldType(mod);
283271 try self.addTypeRelocGlobal(atom_index, ptr_ty, @intCast(u32, index));
284272 // DW.AT.data_member_location, DW.FORM.udata
285273 try dbg_info_buffer.ensureUnusedCapacity(6);
......@@ -304,18 +292,18 @@ pub const DeclState = struct {
304292 // DW.AT.type, DW.FORM.ref4
305293 const index = dbg_info_buffer.items.len;
306294 try dbg_info_buffer.resize(index + 4);
307 try self.addTypeRelocGlobal(atom_index, ty.childType(), @intCast(u32, index));
295 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(u32, index));
308296 }
309297 },
310298 .Array => {
311299 // DW.AT.array_type
312300 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_type));
313301 // DW.AT.name, DW.FORM.string
314 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
302 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
315303 // DW.AT.type, DW.FORM.ref4
316304 var index = dbg_info_buffer.items.len;
317305 try dbg_info_buffer.resize(index + 4);
318 try self.addTypeRelocGlobal(atom_index, ty.childType(), @intCast(u32, index));
306 try self.addTypeRelocGlobal(atom_index, ty.childType(mod), @intCast(u32, index));
319307 // DW.AT.subrange_type
320308 try dbg_info_buffer.append(@enumToInt(AbbrevKind.array_dim));
321309 // DW.AT.type, DW.FORM.ref4
......@@ -323,7 +311,7 @@ pub const DeclState = struct {
323311 try dbg_info_buffer.resize(index + 4);
324312 try self.addTypeRelocGlobal(atom_index, Type.usize, @intCast(u32, index));
325313 // DW.AT.count, DW.FORM.udata
326 const len = ty.arrayLenIncludingSentinel();
314 const len = ty.arrayLenIncludingSentinel(mod);
327315 try leb128.writeULEB128(dbg_info_buffer.writer(), len);
328316 // DW.AT.array_type delimit children
329317 try dbg_info_buffer.append(0);
......@@ -332,15 +320,14 @@ pub const DeclState = struct {
332320 // DW.AT.structure_type
333321 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
334322 // DW.AT.byte_size, DW.FORM.udata
335 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
323 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
336324
337 switch (ty.tag()) {
338 .tuple, .anon_struct => {
325 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
326 .anon_struct_type => |fields| {
339327 // DW.AT.name, DW.FORM.string
340 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(module)});
328 try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(mod)});
341329
342 const fields = ty.tupleFields();
343 for (fields.types, 0..) |field, field_index| {
330 for (fields.types, 0..) |field_ty, field_index| {
344331 // DW.AT.member
345332 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
346333 // DW.AT.name, DW.FORM.string
......@@ -348,29 +335,32 @@ pub const DeclState = struct {
348335 // DW.AT.type, DW.FORM.ref4
349336 var index = dbg_info_buffer.items.len;
350337 try dbg_info_buffer.resize(index + 4);
351 try self.addTypeRelocGlobal(atom_index, field, @intCast(u32, index));
338 try self.addTypeRelocGlobal(atom_index, field_ty.toType(), @intCast(u32, index));
352339 // DW.AT.data_member_location, DW.FORM.udata
353 const field_off = ty.structFieldOffset(field_index, target);
340 const field_off = ty.structFieldOffset(field_index, mod);
354341 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
355342 }
356343 },
357 else => {
344 .struct_type => |struct_type| s: {
345 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse break :s;
358346 // DW.AT.name, DW.FORM.string
359 const struct_name = try ty.nameAllocArena(arena, module);
347 const struct_name = try ty.nameAllocArena(arena, mod);
360348 try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1);
361349 dbg_info_buffer.appendSliceAssumeCapacity(struct_name);
362350 dbg_info_buffer.appendAssumeCapacity(0);
363351
364 const struct_obj = ty.castTag(.@"struct").?.data;
365352 if (struct_obj.layout == .Packed) {
366353 log.debug("TODO implement .debug_info for packed structs", .{});
367354 break :blk;
368355 }
369356
370 const fields = ty.structFields();
371 for (fields.keys(), 0..) |field_name, field_index| {
372 const field = fields.get(field_name).?;
373 if (!field.ty.hasRuntimeBits()) continue;
357 for (
358 struct_obj.fields.keys(),
359 struct_obj.fields.values(),
360 0..,
361 ) |field_name_ip, field, field_index| {
362 if (!field.ty.hasRuntimeBits(mod)) continue;
363 const field_name = mod.intern_pool.stringToSlice(field_name_ip);
374364 // DW.AT.member
375365 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2);
376366 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
......@@ -382,10 +372,11 @@ pub const DeclState = struct {
382372 try dbg_info_buffer.resize(index + 4);
383373 try self.addTypeRelocGlobal(atom_index, field.ty, @intCast(u32, index));
384374 // DW.AT.data_member_location, DW.FORM.udata
385 const field_off = ty.structFieldOffset(field_index, target);
375 const field_off = ty.structFieldOffset(field_index, mod);
386376 try leb128.writeULEB128(dbg_info_buffer.writer(), field_off);
387377 }
388378 },
379 else => unreachable,
389380 }
390381
391382 // DW.AT.structure_type delimit children
......@@ -395,21 +386,16 @@ pub const DeclState = struct {
395386 // DW.AT.enumeration_type
396387 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
397388 // DW.AT.byte_size, DW.FORM.udata
398 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(target));
389 try leb128.writeULEB128(dbg_info_buffer.writer(), ty.abiSize(mod));
399390 // DW.AT.name, DW.FORM.string
400 const enum_name = try ty.nameAllocArena(arena, module);
391 const enum_name = try ty.nameAllocArena(arena, mod);
401392 try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1);
402393 dbg_info_buffer.appendSliceAssumeCapacity(enum_name);
403394 dbg_info_buffer.appendAssumeCapacity(0);
404395
405 const fields = ty.enumFields();
406 const values: ?Module.EnumFull.ValueMap = switch (ty.tag()) {
407 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values,
408 .enum_simple => null,
409 .enum_numbered => ty.castTag(.enum_numbered).?.data.values,
410 else => unreachable,
411 };
412 for (fields.keys(), 0..) |field_name, field_i| {
396 const enum_type = mod.intern_pool.indexToKey(ty.ip_index).enum_type;
397 for (enum_type.names, 0..) |field_name_index, field_i| {
398 const field_name = mod.intern_pool.stringToSlice(field_name_index);
413399 // DW.AT.enumerator
414400 try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64));
415401 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
......@@ -417,15 +403,14 @@ pub const DeclState = struct {
417403 dbg_info_buffer.appendSliceAssumeCapacity(field_name);
418404 dbg_info_buffer.appendAssumeCapacity(0);
419405 // DW.AT.const_value, DW.FORM.data8
420 const value: u64 = if (values) |vals| value: {
421 if (vals.count() == 0) break :value @intCast(u64, field_i); // auto-numbered
422 const value = vals.keys()[field_i];
406 const value: u64 = value: {
407 if (enum_type.values.len == 0) break :value field_i; // auto-numbered
408 const value = enum_type.values[field_i];
423409 // TODO do not assume a 64bit enum value - could be bigger.
424410 // See https://github.com/ziglang/zig/issues/645
425 var int_buffer: Value.Payload.U64 = undefined;
426 const field_int_val = value.enumToInt(ty, &int_buffer);
427 break :value @bitCast(u64, field_int_val.toSignedInt(target));
428 } else @intCast(u64, field_i);
411 const field_int_val = try value.toValue().enumToInt(ty, mod);
412 break :value @bitCast(u64, field_int_val.toSignedInt(mod));
413 };
429414 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian);
430415 }
431416
......@@ -433,12 +418,12 @@ pub const DeclState = struct {
433418 try dbg_info_buffer.append(0);
434419 },
435420 .Union => {
436 const layout = ty.unionGetLayout(target);
437 const union_obj = ty.cast(Type.Payload.Union).?.data;
421 const layout = ty.unionGetLayout(mod);
422 const union_obj = mod.typeToUnion(ty).?;
438423 const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0;
439424 const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size;
440425 const is_tagged = layout.tag_size > 0;
441 const union_name = try ty.nameAllocArena(arena, module);
426 const union_name = try ty.nameAllocArena(arena, mod);
442427
443428 // TODO this is temporary to match current state of unions in Zig - we don't yet have
444429 // safety checks implemented meaning the implicit tag is not yet stored and generated
......@@ -478,14 +463,15 @@ pub const DeclState = struct {
478463 try dbg_info_buffer.writer().print("{s}\x00", .{union_name});
479464 }
480465
481 const fields = ty.unionFields();
466 const fields = ty.unionFields(mod);
482467 for (fields.keys()) |field_name| {
483468 const field = fields.get(field_name).?;
484 if (!field.ty.hasRuntimeBits()) continue;
469 if (!field.ty.hasRuntimeBits(mod)) continue;
485470 // DW.AT.member
486471 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_member));
487472 // DW.AT.name, DW.FORM.string
488 try dbg_info_buffer.writer().print("{s}\x00", .{field_name});
473 try dbg_info_buffer.appendSlice(mod.intern_pool.stringToSlice(field_name));
474 try dbg_info_buffer.append(0);
489475 // DW.AT.type, DW.FORM.ref4
490476 const index = dbg_info_buffer.items.len;
491477 try dbg_info_buffer.resize(index + 4);
......@@ -517,30 +503,30 @@ pub const DeclState = struct {
517503 .ErrorSet => {
518504 try addDbgInfoErrorSet(
519505 self.abbrev_type_arena.allocator(),
520 module,
506 mod,
521507 ty,
522508 target,
523509 &self.dbg_info,
524510 );
525511 },
526512 .ErrorUnion => {
527 const error_ty = ty.errorUnionSet();
528 const payload_ty = ty.errorUnionPayload();
529 const payload_align = if (payload_ty.isNoReturn()) 0 else payload_ty.abiAlignment(target);
530 const error_align = Type.anyerror.abiAlignment(target);
531 const abi_size = ty.abiSize(target);
532 const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(target) else 0;
533 const error_off = if (error_align >= payload_align) 0 else payload_ty.abiSize(target);
513 const error_ty = ty.errorUnionSet(mod);
514 const payload_ty = ty.errorUnionPayload(mod);
515 const payload_align = if (payload_ty.isNoReturn(mod)) 0 else payload_ty.abiAlignment(mod);
516 const error_align = Type.anyerror.abiAlignment(mod);
517 const abi_size = ty.abiSize(mod);
518 const payload_off = if (error_align >= payload_align) Type.anyerror.abiSize(mod) else 0;
519 const error_off = if (error_align >= payload_align) 0 else payload_ty.abiSize(mod);
534520
535521 // DW.AT.structure_type
536522 try dbg_info_buffer.append(@enumToInt(AbbrevKind.struct_type));
537523 // DW.AT.byte_size, DW.FORM.udata
538524 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
539525 // DW.AT.name, DW.FORM.string
540 const name = try ty.nameAllocArena(arena, module);
526 const name = try ty.nameAllocArena(arena, mod);
541527 try dbg_info_buffer.writer().print("{s}\x00", .{name});
542528
543 if (!payload_ty.isNoReturn()) {
529 if (!payload_ty.isNoReturn(mod)) {
544530 // DW.AT.member
545531 try dbg_info_buffer.ensureUnusedCapacity(7);
546532 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.struct_member));
......@@ -685,9 +671,10 @@ pub const DeclState = struct {
685671 const atom_index = self.di_atom_decls.get(owner_decl).?;
686672 const name_with_null = name.ptr[0 .. name.len + 1];
687673 try dbg_info.append(@enumToInt(AbbrevKind.variable));
688 const target = self.mod.getTarget();
674 const mod = self.mod;
675 const target = mod.getTarget();
689676 const endian = target.cpu.arch.endian();
690 const child_ty = if (is_ptr) ty.childType() else ty;
677 const child_ty = if (is_ptr) ty.childType(mod) else ty;
691678
692679 switch (loc) {
693680 .register => |reg| {
......@@ -790,9 +777,9 @@ pub const DeclState = struct {
790777 const fixup = dbg_info.items.len;
791778 dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT.location, DW.FORM.exprloc
792779 1,
793 if (child_ty.isSignedInt()) DW.OP.consts else DW.OP.constu,
780 if (child_ty.isSignedInt(mod)) DW.OP.consts else DW.OP.constu,
794781 });
795 if (child_ty.isSignedInt()) {
782 if (child_ty.isSignedInt(mod)) {
796783 try leb128.writeILEB128(dbg_info.writer(), @bitCast(i64, x));
797784 } else {
798785 try leb128.writeULEB128(dbg_info.writer(), x);
......@@ -805,7 +792,7 @@ pub const DeclState = struct {
805792 // DW.AT.location, DW.FORM.exprloc
806793 // uleb128(exprloc_len)
807794 // DW.OP.implicit_value uleb128(len_of_bytes) bytes
808 const abi_size = @intCast(u32, child_ty.abiSize(target));
795 const abi_size = @intCast(u32, child_ty.abiSize(mod));
809796 var implicit_value_len = std.ArrayList(u8).init(self.gpa);
810797 defer implicit_value_len.deinit();
811798 try leb128.writeULEB128(implicit_value_len.writer(), abi_size);
......@@ -964,8 +951,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
964951 defer tracy.end();
965952
966953 const decl = mod.declPtr(decl_index);
967 const decl_name = try decl.getFullyQualifiedName(mod);
968 defer self.allocator.free(decl_name);
954 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
969955
970956 log.debug("initDeclState {s}{*}", .{ decl_name, decl });
971957
......@@ -979,14 +965,14 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
979965
980966 assert(decl.has_tv);
981967
982 switch (decl.ty.zigTypeTag()) {
968 switch (decl.ty.zigTypeTag(mod)) {
983969 .Fn => {
984970 _ = try self.getOrCreateAtomForDecl(.src_fn, decl_index);
985971
986972 // For functions we need to add a prologue to the debug line program.
987973 try dbg_line_buffer.ensureTotalCapacity(26);
988974
989 const func = decl.val.castTag(.function).?.data;
975 const func = decl.val.getFunction(mod).?;
990976 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
991977 decl.src_line,
992978 func.lbrace_line,
......@@ -1026,8 +1012,8 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
10261012 const decl_name_with_null = decl_name[0 .. decl_name.len + 1];
10271013 try dbg_info_buffer.ensureUnusedCapacity(25 + decl_name_with_null.len);
10281014
1029 const fn_ret_type = decl.ty.fnReturnType();
1030 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits();
1015 const fn_ret_type = decl.ty.fnReturnType(mod);
1016 const fn_ret_has_bits = fn_ret_type.hasRuntimeBits(mod);
10311017 if (fn_ret_has_bits) {
10321018 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.subprogram));
10331019 } else {
......@@ -1059,7 +1045,7 @@ pub fn initDeclState(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index)
10591045
10601046pub fn commitDeclState(
10611047 self: *Dwarf,
1062 module: *Module,
1048 mod: *Module,
10631049 decl_index: Module.Decl.Index,
10641050 sym_addr: u64,
10651051 sym_size: u64,
......@@ -1071,12 +1057,12 @@ pub fn commitDeclState(
10711057 const gpa = self.allocator;
10721058 var dbg_line_buffer = &decl_state.dbg_line;
10731059 var dbg_info_buffer = &decl_state.dbg_info;
1074 const decl = module.declPtr(decl_index);
1060 const decl = mod.declPtr(decl_index);
10751061
10761062 const target_endian = self.target.cpu.arch.endian();
10771063
10781064 assert(decl.has_tv);
1079 switch (decl.ty.zigTypeTag()) {
1065 switch (decl.ty.zigTypeTag(mod)) {
10801066 .Fn => {
10811067 // Since the Decl is a function, we need to update the .debug_line program.
10821068 // Perform the relocations based on vaddr.
......@@ -1271,10 +1257,11 @@ pub fn commitDeclState(
12711257 const symbol = &decl_state.abbrev_table.items[sym_index];
12721258 const ty = symbol.type;
12731259 const deferred: bool = blk: {
1274 if (ty.isAnyError()) break :blk true;
1275 switch (ty.tag()) {
1276 .error_set_inferred => {
1277 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
1260 if (ty.isAnyError(mod)) break :blk true;
1261 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1262 .inferred_error_set_type => |ies_index| {
1263 const ies = mod.inferredErrorSetPtr(ies_index);
1264 if (!ies.is_resolved) break :blk true;
12781265 },
12791266 else => {},
12801267 }
......@@ -1283,11 +1270,10 @@ pub fn commitDeclState(
12831270 if (deferred) continue;
12841271
12851272 symbol.offset = @intCast(u32, dbg_info_buffer.items.len);
1286 try decl_state.addDbgInfoType(module, di_atom_index, ty);
1273 try decl_state.addDbgInfoType(mod, di_atom_index, ty);
12871274 }
12881275 }
12891276
1290 log.debug("updateDeclDebugInfoAllocation for '{s}'", .{decl.name});
12911277 try self.updateDeclDebugInfoAllocation(di_atom_index, @intCast(u32, dbg_info_buffer.items.len));
12921278
12931279 while (decl_state.abbrev_relocs.popOrNull()) |reloc| {
......@@ -1295,10 +1281,11 @@ pub fn commitDeclState(
12951281 const symbol = decl_state.abbrev_table.items[target];
12961282 const ty = symbol.type;
12971283 const deferred: bool = blk: {
1298 if (ty.isAnyError()) break :blk true;
1299 switch (ty.tag()) {
1300 .error_set_inferred => {
1301 if (!ty.castTag(.error_set_inferred).?.data.is_resolved) break :blk true;
1284 if (ty.isAnyError(mod)) break :blk true;
1285 switch (mod.intern_pool.indexToKey(ty.ip_index)) {
1286 .inferred_error_set_type => |ies_index| {
1287 const ies = mod.inferredErrorSetPtr(ies_index);
1288 if (!ies.is_resolved) break :blk true;
13021289 },
13031290 else => {},
13041291 }
......@@ -1319,7 +1306,7 @@ pub fn commitDeclState(
13191306 reloc.offset,
13201307 value,
13211308 target,
1322 ty.fmt(module),
1309 ty.fmt(mod),
13231310 });
13241311 mem.writeInt(
13251312 u32,
......@@ -1358,7 +1345,6 @@ pub fn commitDeclState(
13581345 }
13591346 }
13601347
1361 log.debug("writeDeclDebugInfo for '{s}", .{decl.name});
13621348 try self.writeDeclDebugInfo(di_atom_index, dbg_info_buffer.items);
13631349}
13641350
......@@ -1527,7 +1513,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom_index: Atom.Index, dbg_info_buf: []cons
15271513 }
15281514}
15291515
1530pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.Decl.Index) !void {
1516pub fn updateDeclLineNumber(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !void {
15311517 const tracy = trace(@src());
15321518 defer tracy.end();
15331519
......@@ -1535,8 +1521,8 @@ pub fn updateDeclLineNumber(self: *Dwarf, module: *Module, decl_index: Module.De
15351521 const atom = self.getAtom(.src_fn, atom_index);
15361522 if (atom.len == 0) return;
15371523
1538 const decl = module.declPtr(decl_index);
1539 const func = decl.val.castTag(.function).?.data;
1524 const decl = mod.declPtr(decl_index);
1525 const func = decl.val.getFunction(mod).?;
15401526 log.debug("decl.src_line={d}, func.lbrace_line={d}, func.rbrace_line={d}", .{
15411527 decl.src_line,
15421528 func.lbrace_line,
......@@ -2534,18 +2520,14 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
25342520 defer arena_alloc.deinit();
25352521 const arena = arena_alloc.allocator();
25362522
2537 const error_set = try arena.create(Module.ErrorSet);
2538 const error_ty = try Type.Tag.error_set.create(arena, error_set);
2539 var names = Module.ErrorSet.NameMap{};
2540 try names.ensureUnusedCapacity(arena, module.global_error_set.count());
2541 var it = module.global_error_set.keyIterator();
2542 while (it.next()) |key| {
2543 names.putAssumeCapacityNoClobber(key.*, {});
2544 }
2545 error_set.names = names;
2523 // TODO: don't create a zig type for this, just make the dwarf info
2524 // without touching the zig type system.
2525 const names = try arena.dupe(InternPool.NullTerminatedString, module.global_error_set.keys());
2526 std.mem.sort(InternPool.NullTerminatedString, names, {}, InternPool.NullTerminatedString.indexLessThan);
25462527
2528 const error_ty = try module.intern(.{ .error_set_type = .{ .names = names } });
25472529 var dbg_info_buffer = std.ArrayList(u8).init(arena);
2548 try addDbgInfoErrorSet(arena, module, error_ty, self.target, &dbg_info_buffer);
2530 try addDbgInfoErrorSet(arena, module, error_ty.toType(), self.target, &dbg_info_buffer);
25492531
25502532 const di_atom_index = try self.createAtom(.di_atom);
25512533 log.debug("updateDeclDebugInfoAllocation in flushModule", .{});
......@@ -2598,7 +2580,7 @@ pub fn flushModule(self: *Dwarf, module: *Module) !void {
25982580
25992581fn addDIFile(self: *Dwarf, mod: *Module, decl_index: Module.Decl.Index) !u28 {
26002582 const decl = mod.declPtr(decl_index);
2601 const file_scope = decl.getFileScope();
2583 const file_scope = decl.getFileScope(mod);
26022584 const gop = try self.di_files.getOrPut(self.allocator, file_scope);
26032585 if (!gop.found_existing) {
26042586 switch (self.bin_file.tag) {
......@@ -2663,7 +2645,7 @@ fn genIncludeDirsAndFileNames(self: *Dwarf, arena: Allocator) !struct {
26632645
26642646fn addDbgInfoErrorSet(
26652647 arena: Allocator,
2666 module: *Module,
2648 mod: *Module,
26672649 ty: Type,
26682650 target: std.Target,
26692651 dbg_info_buffer: *std.ArrayList(u8),
......@@ -2673,10 +2655,10 @@ fn addDbgInfoErrorSet(
26732655 // DW.AT.enumeration_type
26742656 try dbg_info_buffer.append(@enumToInt(AbbrevKind.enum_type));
26752657 // DW.AT.byte_size, DW.FORM.udata
2676 const abi_size = Type.anyerror.abiSize(target);
2658 const abi_size = Type.anyerror.abiSize(mod);
26772659 try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size);
26782660 // DW.AT.name, DW.FORM.string
2679 const name = try ty.nameAllocArena(arena, module);
2661 const name = try ty.nameAllocArena(arena, mod);
26802662 try dbg_info_buffer.writer().print("{s}\x00", .{name});
26812663
26822664 // DW.AT.enumerator
......@@ -2689,9 +2671,10 @@ fn addDbgInfoErrorSet(
26892671 // DW.AT.const_value, DW.FORM.data8
26902672 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
26912673
2692 const error_names = ty.errorSetNames();
2693 for (error_names) |error_name| {
2694 const kv = module.getErrorValue(error_name) catch unreachable;
2674 const error_names = ty.errorSetNames(mod);
2675 for (error_names) |error_name_ip| {
2676 const int = try mod.getErrorValue(error_name_ip);
2677 const error_name = mod.intern_pool.stringToSlice(error_name_ip);
26952678 // DW.AT.enumerator
26962679 try dbg_info_buffer.ensureUnusedCapacity(error_name.len + 2 + @sizeOf(u64));
26972680 dbg_info_buffer.appendAssumeCapacity(@enumToInt(AbbrevKind.enum_variant));
......@@ -2699,7 +2682,7 @@ fn addDbgInfoErrorSet(
26992682 dbg_info_buffer.appendSliceAssumeCapacity(error_name);
27002683 dbg_info_buffer.appendAssumeCapacity(0);
27012684 // DW.AT.const_value, DW.FORM.data8
2702 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), kv.value, target_endian);
2685 mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), int, target_endian);
27032686 }
27042687
27052688 // DW.AT.enumeration_type delimit children
src/link/Elf.zig+63-58
......@@ -28,6 +28,7 @@ const File = link.File;
2828const Liveness = @import("../Liveness.zig");
2929const LlvmObject = @import("../codegen/llvm.zig").Object;
3030const Module = @import("../Module.zig");
31const InternPool = @import("../InternPool.zig");
3132const Package = @import("../Package.zig");
3233const StringTable = @import("strtab.zig").StringTable;
3334const TableSection = @import("table_section.zig").TableSection;
......@@ -2414,7 +2415,8 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {
24142415}
24152416
24162417pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Index {
2417 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
2418 const mod = self.base.options.module.?;
2419 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod));
24182420 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
24192421 if (!gop.found_existing) gop.value_ptr.* = .{};
24202422 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
......@@ -2429,7 +2431,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Inde
24292431 metadata.state.* = .pending_flush;
24302432 const atom = metadata.atom.*;
24312433 // anyerror needs to be deferred until flushModule
2432 if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
2434 if (sym.getDecl(mod) != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
24332435 .code => self.text_section_index.?,
24342436 .const_data => self.rodata_section_index.?,
24352437 });
......@@ -2449,12 +2451,13 @@ pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.I
24492451}
24502452
24512453fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {
2452 const decl = self.base.options.module.?.declPtr(decl_index);
2454 const mod = self.base.options.module.?;
2455 const decl = mod.declPtr(decl_index);
24532456 const ty = decl.ty;
2454 const zig_ty = ty.zigTypeTag();
2457 const zig_ty = ty.zigTypeTag(mod);
24552458 const val = decl.val;
24562459 const shdr_index: u16 = blk: {
2457 if (val.isUndefDeep()) {
2460 if (val.isUndefDeep(mod)) {
24582461 // TODO in release-fast and release-small, we should put undef in .bss
24592462 break :blk self.data_section_index.?;
24602463 }
......@@ -2463,7 +2466,7 @@ fn getDeclShdrIndex(self: *Elf, decl_index: Module.Decl.Index) u16 {
24632466 // TODO: what if this is a function pointer?
24642467 .Fn => break :blk self.text_section_index.?,
24652468 else => {
2466 if (val.castTag(.variable)) |_| {
2469 if (val.getVariable(mod)) |_| {
24672470 break :blk self.data_section_index.?;
24682471 }
24692472 break :blk self.rodata_section_index.?;
......@@ -2478,11 +2481,10 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
24782481 const mod = self.base.options.module.?;
24792482 const decl = mod.declPtr(decl_index);
24802483
2481 const decl_name = try decl.getFullyQualifiedName(mod);
2482 defer self.base.allocator.free(decl_name);
2484 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
24832485
24842486 log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });
2485 const required_alignment = decl.getAlignment(self.base.options.target);
2487 const required_alignment = decl.getAlignment(mod);
24862488
24872489 const decl_metadata = self.decls.get(decl_index).?;
24882490 const atom_index = decl_metadata.atom;
......@@ -2572,19 +2574,20 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
25722574 return local_sym;
25732575}
25742576
2575pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
2577pub fn updateFunc(self: *Elf, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
25762578 if (build_options.skip_non_native and builtin.object_format != .elf) {
25772579 @panic("Attempted to compile for object format that was disabled by build configuration");
25782580 }
25792581 if (build_options.have_llvm) {
2580 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(module, func, air, liveness);
2582 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness);
25812583 }
25822584
25832585 const tracy = trace(@src());
25842586 defer tracy.end();
25852587
2588 const func = mod.funcPtr(func_index);
25862589 const decl_index = func.owner_decl;
2587 const decl = module.declPtr(decl_index);
2590 const decl = mod.declPtr(decl_index);
25882591
25892592 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
25902593 self.freeUnnamedConsts(decl_index);
......@@ -2593,28 +2596,28 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
25932596 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
25942597 defer code_buffer.deinit();
25952598
2596 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl_index) else null;
2599 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(mod, decl_index) else null;
25972600 defer if (decl_state) |*ds| ds.deinit();
25982601
25992602 const res = if (decl_state) |*ds|
2600 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
2603 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .{
26012604 .dwarf = ds,
26022605 })
26032606 else
2604 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
2607 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .none);
26052608
26062609 const code = switch (res) {
26072610 .ok => code_buffer.items,
26082611 .fail => |em| {
26092612 decl.analysis = .codegen_failure;
2610 try module.failed_decls.put(module.gpa, decl_index, em);
2613 try mod.failed_decls.put(mod.gpa, decl_index, em);
26112614 return;
26122615 },
26132616 };
26142617 const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_FUNC);
26152618 if (decl_state) |*ds| {
26162619 try self.dwarf.?.commitDeclState(
2617 module,
2620 mod,
26182621 decl_index,
26192622 local_sym.st_value,
26202623 local_sym.st_size,
......@@ -2624,31 +2627,30 @@ pub fn updateFunc(self: *Elf, module: *Module, func: *Module.Fn, air: Air, liven
26242627
26252628 // Since we updated the vaddr and the size, each corresponding export
26262629 // symbol also needs to be updated.
2627 return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
2630 return self.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
26282631}
26292632
26302633pub fn updateDecl(
26312634 self: *Elf,
2632 module: *Module,
2635 mod: *Module,
26332636 decl_index: Module.Decl.Index,
26342637) File.UpdateDeclError!void {
26352638 if (build_options.skip_non_native and builtin.object_format != .elf) {
26362639 @panic("Attempted to compile for object format that was disabled by build configuration");
26372640 }
26382641 if (build_options.have_llvm) {
2639 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl_index);
2642 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
26402643 }
26412644
26422645 const tracy = trace(@src());
26432646 defer tracy.end();
26442647
2645 const decl = module.declPtr(decl_index);
2648 const decl = mod.declPtr(decl_index);
26462649
2647 if (decl.val.tag() == .extern_fn) {
2650 if (decl.val.getExternFunc(mod)) |_| {
26482651 return; // TODO Should we do more when front-end analyzed extern decl?
26492652 }
2650 if (decl.val.castTag(.variable)) |payload| {
2651 const variable = payload.data;
2653 if (decl.val.getVariable(mod)) |variable| {
26522654 if (variable.is_extern) {
26532655 return; // TODO Should we do more when front-end analyzed extern decl?
26542656 }
......@@ -2661,13 +2663,13 @@ pub fn updateDecl(
26612663 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
26622664 defer code_buffer.deinit();
26632665
2664 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(module, decl_index) else null;
2666 var decl_state: ?Dwarf.DeclState = if (self.dwarf) |*dw| try dw.initDeclState(mod, decl_index) else null;
26652667 defer if (decl_state) |*ds| ds.deinit();
26662668
26672669 // TODO implement .debug_info for global variables
2668 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2670 const decl_val = if (decl.val.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
26692671 const res = if (decl_state) |*ds|
2670 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2672 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
26712673 .ty = decl.ty,
26722674 .val = decl_val,
26732675 }, &code_buffer, .{
......@@ -2676,7 +2678,7 @@ pub fn updateDecl(
26762678 .parent_atom_index = atom.getSymbolIndex().?,
26772679 })
26782680 else
2679 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2681 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
26802682 .ty = decl.ty,
26812683 .val = decl_val,
26822684 }, &code_buffer, .none, .{
......@@ -2687,7 +2689,7 @@ pub fn updateDecl(
26872689 .ok => code_buffer.items,
26882690 .fail => |em| {
26892691 decl.analysis = .codegen_failure;
2690 try module.failed_decls.put(module.gpa, decl_index, em);
2692 try mod.failed_decls.put(mod.gpa, decl_index, em);
26912693 return;
26922694 },
26932695 };
......@@ -2695,7 +2697,7 @@ pub fn updateDecl(
26952697 const local_sym = try self.updateDeclCode(decl_index, code, elf.STT_OBJECT);
26962698 if (decl_state) |*ds| {
26972699 try self.dwarf.?.commitDeclState(
2698 module,
2700 mod,
26992701 decl_index,
27002702 local_sym.st_value,
27012703 local_sym.st_size,
......@@ -2705,7 +2707,7 @@ pub fn updateDecl(
27052707
27062708 // Since we updated the vaddr and the size, each corresponding export
27072709 // symbol also needs to be updated.
2708 return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
2710 return self.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
27092711}
27102712
27112713fn updateLazySymbolAtom(
......@@ -2734,8 +2736,8 @@ fn updateLazySymbolAtom(
27342736 const atom = self.getAtom(atom_index);
27352737 const local_sym_index = atom.getSymbolIndex().?;
27362738
2737 const src = if (sym.ty.getOwnerDeclOrNull()) |owner_decl|
2738 mod.declPtr(owner_decl).srcLoc()
2739 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
2740 mod.declPtr(owner_decl).srcLoc(mod)
27392741 else
27402742 Module.SrcLoc{
27412743 .file_scope = undefined,
......@@ -2800,8 +2802,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28002802
28012803 const decl = mod.declPtr(decl_index);
28022804 const name_str_index = blk: {
2803 const decl_name = try decl.getFullyQualifiedName(mod);
2804 defer gpa.free(decl_name);
2805 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
28052806 const index = unnamed_consts.items.len;
28062807 const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index });
28072808 defer gpa.free(name);
......@@ -2811,7 +2812,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28112812
28122813 const atom_index = try self.createAtom();
28132814
2814 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .{
2815 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .{
28152816 .none = {},
28162817 }, .{
28172818 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
......@@ -2826,7 +2827,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28262827 },
28272828 };
28282829
2829 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
2830 const required_alignment = typed_value.ty.abiAlignment(mod);
28302831 const shdr_index = self.rodata_section_index.?;
28312832 const phdr_index = self.sections.items(.phdr_index)[shdr_index];
28322833 const local_sym = self.getAtom(atom_index).getSymbolPtr(self);
......@@ -2852,7 +2853,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: Module
28522853
28532854pub fn updateDeclExports(
28542855 self: *Elf,
2855 module: *Module,
2856 mod: *Module,
28562857 decl_index: Module.Decl.Index,
28572858 exports: []const *Module.Export,
28582859) File.UpdateDeclExportsError!void {
......@@ -2860,7 +2861,7 @@ pub fn updateDeclExports(
28602861 @panic("Attempted to compile for object format that was disabled by build configuration");
28612862 }
28622863 if (build_options.have_llvm) {
2863 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(module, decl_index, exports);
2864 if (self.llvm_object) |llvm_object| return llvm_object.updateDeclExports(mod, decl_index, exports);
28642865 }
28652866
28662867 const tracy = trace(@src());
......@@ -2868,7 +2869,7 @@ pub fn updateDeclExports(
28682869
28692870 const gpa = self.base.allocator;
28702871
2871 const decl = module.declPtr(decl_index);
2872 const decl = mod.declPtr(decl_index);
28722873 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
28732874 const atom = self.getAtom(atom_index);
28742875 const decl_sym = atom.getSymbol(self);
......@@ -2878,40 +2879,41 @@ pub fn updateDeclExports(
28782879 try self.global_symbols.ensureUnusedCapacity(gpa, exports.len);
28792880
28802881 for (exports) |exp| {
2881 if (exp.options.section) |section_name| {
2882 if (!mem.eql(u8, section_name, ".text")) {
2883 try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);
2884 module.failed_exports.putAssumeCapacityNoClobber(
2882 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
2883 if (exp.opts.section.unwrap()) |section_name| {
2884 if (!mod.intern_pool.stringEqlSlice(section_name, ".text")) {
2885 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
2886 mod.failed_exports.putAssumeCapacityNoClobber(
28852887 exp,
2886 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: ExportOptions.section", .{}),
2888 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(mod), "Unimplemented: ExportOptions.section", .{}),
28872889 );
28882890 continue;
28892891 }
28902892 }
2891 const stb_bits: u8 = switch (exp.options.linkage) {
2893 const stb_bits: u8 = switch (exp.opts.linkage) {
28922894 .Internal => elf.STB_LOCAL,
28932895 .Strong => blk: {
28942896 const entry_name = self.base.options.entry orelse "_start";
2895 if (mem.eql(u8, exp.options.name, entry_name)) {
2897 if (mem.eql(u8, exp_name, entry_name)) {
28962898 self.entry_addr = decl_sym.st_value;
28972899 }
28982900 break :blk elf.STB_GLOBAL;
28992901 },
29002902 .Weak => elf.STB_WEAK,
29012903 .LinkOnce => {
2902 try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);
2903 module.failed_exports.putAssumeCapacityNoClobber(
2904 try mod.failed_exports.ensureUnusedCapacity(mod.gpa, 1);
2905 mod.failed_exports.putAssumeCapacityNoClobber(
29042906 exp,
2905 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: GlobalLinkage.LinkOnce", .{}),
2907 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(mod), "Unimplemented: GlobalLinkage.LinkOnce", .{}),
29062908 );
29072909 continue;
29082910 },
29092911 };
29102912 const stt_bits: u8 = @truncate(u4, decl_sym.st_info);
2911 if (decl_metadata.getExport(self, exp.options.name)) |i| {
2913 if (decl_metadata.getExport(self, exp_name)) |i| {
29122914 const sym = &self.global_symbols.items[i];
29132915 sym.* = .{
2914 .st_name = try self.shstrtab.insert(gpa, exp.options.name),
2916 .st_name = try self.shstrtab.insert(gpa, exp_name),
29152917 .st_info = (stb_bits << 4) | stt_bits,
29162918 .st_other = 0,
29172919 .st_shndx = shdr_index,
......@@ -2925,7 +2927,7 @@ pub fn updateDeclExports(
29252927 };
29262928 try decl_metadata.exports.append(gpa, @intCast(u32, i));
29272929 self.global_symbols.items[i] = .{
2928 .st_name = try self.shstrtab.insert(gpa, exp.options.name),
2930 .st_name = try self.shstrtab.insert(gpa, exp_name),
29292931 .st_info = (stb_bits << 4) | stt_bits,
29302932 .st_other = 0,
29312933 .st_shndx = shdr_index,
......@@ -2942,8 +2944,7 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: Module.Decl.In
29422944 defer tracy.end();
29432945
29442946 const decl = mod.declPtr(decl_index);
2945 const decl_name = try decl.getFullyQualifiedName(mod);
2946 defer self.base.allocator.free(decl_name);
2947 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
29472948
29482949 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
29492950
......@@ -2953,11 +2954,15 @@ pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: Module.Decl.In
29532954 }
29542955}
29552956
2956pub fn deleteDeclExport(self: *Elf, decl_index: Module.Decl.Index, name: []const u8) void {
2957pub fn deleteDeclExport(
2958 self: *Elf,
2959 decl_index: Module.Decl.Index,
2960 name: InternPool.NullTerminatedString,
2961) void {
29572962 if (self.llvm_object) |_| return;
29582963 const metadata = self.decls.getPtr(decl_index) orelse return;
2959 const sym_index = metadata.getExportPtr(self, name) orelse return;
2960 log.debug("deleting export '{s}'", .{name});
2964 const mod = self.base.options.module.?;
2965 const sym_index = metadata.getExportPtr(self, mod.intern_pool.stringToSlice(name)) orelse return;
29612966 self.global_symbol_free_list.append(self.base.allocator, sym_index.*) catch {};
29622967 self.global_symbols.items[sym_index.*].st_info = 0;
29632968 sym_index.* = 0;
src/link/MachO.zig+76-68
......@@ -40,6 +40,7 @@ const Liveness = @import("../Liveness.zig");
4040const LlvmObject = @import("../codegen/llvm.zig").Object;
4141const Md5 = std.crypto.hash.Md5;
4242const Module = @import("../Module.zig");
43const InternPool = @import("../InternPool.zig");
4344const Relocation = @import("MachO/Relocation.zig");
4445const StringTable = @import("strtab.zig").StringTable;
4546const TableSection = @import("table_section.zig").TableSection;
......@@ -1847,18 +1848,19 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
18471848 self.markRelocsDirtyByTarget(target);
18481849}
18491850
1850pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1851pub fn updateFunc(self: *MachO, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
18511852 if (build_options.skip_non_native and builtin.object_format != .macho) {
18521853 @panic("Attempted to compile for object format that was disabled by build configuration");
18531854 }
18541855 if (build_options.have_llvm) {
1855 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(module, func, air, liveness);
1856 if (self.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness);
18561857 }
18571858 const tracy = trace(@src());
18581859 defer tracy.end();
18591860
1861 const func = mod.funcPtr(func_index);
18601862 const decl_index = func.owner_decl;
1861 const decl = module.declPtr(decl_index);
1863 const decl = mod.declPtr(decl_index);
18621864
18631865 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
18641866 self.freeUnnamedConsts(decl_index);
......@@ -1868,23 +1870,23 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
18681870 defer code_buffer.deinit();
18691871
18701872 var decl_state = if (self.d_sym) |*d_sym|
1871 try d_sym.dwarf.initDeclState(module, decl_index)
1873 try d_sym.dwarf.initDeclState(mod, decl_index)
18721874 else
18731875 null;
18741876 defer if (decl_state) |*ds| ds.deinit();
18751877
18761878 const res = if (decl_state) |*ds|
1877 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
1879 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .{
18781880 .dwarf = ds,
18791881 })
18801882 else
1881 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
1883 try codegen.generateFunction(&self.base, decl.srcLoc(mod), func_index, air, liveness, &code_buffer, .none);
18821884
18831885 var code = switch (res) {
18841886 .ok => code_buffer.items,
18851887 .fail => |em| {
18861888 decl.analysis = .codegen_failure;
1887 try module.failed_decls.put(module.gpa, decl_index, em);
1889 try mod.failed_decls.put(mod.gpa, decl_index, em);
18881890 return;
18891891 },
18901892 };
......@@ -1893,7 +1895,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
18931895
18941896 if (decl_state) |*ds| {
18951897 try self.d_sym.?.dwarf.commitDeclState(
1896 module,
1898 mod,
18971899 decl_index,
18981900 addr,
18991901 self.getAtom(atom_index).size,
......@@ -1903,7 +1905,7 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
19031905
19041906 // Since we updated the vaddr and the size, each corresponding export symbol also
19051907 // needs to be updated.
1906 try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
1908 try self.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
19071909}
19081910
19091911pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Module.Decl.Index) !u32 {
......@@ -1912,16 +1914,15 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
19121914 var code_buffer = std.ArrayList(u8).init(gpa);
19131915 defer code_buffer.deinit();
19141916
1915 const module = self.base.options.module.?;
1917 const mod = self.base.options.module.?;
19161918 const gop = try self.unnamed_const_atoms.getOrPut(gpa, decl_index);
19171919 if (!gop.found_existing) {
19181920 gop.value_ptr.* = .{};
19191921 }
19201922 const unnamed_consts = gop.value_ptr;
19211923
1922 const decl = module.declPtr(decl_index);
1923 const decl_name = try decl.getFullyQualifiedName(module);
1924 defer gpa.free(decl_name);
1924 const decl = mod.declPtr(decl_index);
1925 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
19251926
19261927 const name_str_index = blk: {
19271928 const index = unnamed_consts.items.len;
......@@ -1935,20 +1936,20 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
19351936
19361937 const atom_index = try self.createAtom();
19371938
1938 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{
1939 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .none, .{
19391940 .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
19401941 });
19411942 var code = switch (res) {
19421943 .ok => code_buffer.items,
19431944 .fail => |em| {
19441945 decl.analysis = .codegen_failure;
1945 try module.failed_decls.put(module.gpa, decl_index, em);
1946 try mod.failed_decls.put(mod.gpa, decl_index, em);
19461947 log.err("{s}", .{em.msg});
19471948 return error.CodegenFail;
19481949 },
19491950 };
19501951
1951 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
1952 const required_alignment = typed_value.ty.abiAlignment(mod);
19521953 const atom = self.getAtomPtr(atom_index);
19531954 atom.size = code.len;
19541955 // TODO: work out logic for disambiguating functions from function pointers
......@@ -1971,33 +1972,32 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
19711972 return atom.getSymbolIndex().?;
19721973}
19731974
1974pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void {
1975pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !void {
19751976 if (build_options.skip_non_native and builtin.object_format != .macho) {
19761977 @panic("Attempted to compile for object format that was disabled by build configuration");
19771978 }
19781979 if (build_options.have_llvm) {
1979 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(module, decl_index);
1980 if (self.llvm_object) |llvm_object| return llvm_object.updateDecl(mod, decl_index);
19801981 }
19811982 const tracy = trace(@src());
19821983 defer tracy.end();
19831984
1984 const decl = module.declPtr(decl_index);
1985 const decl = mod.declPtr(decl_index);
19851986
1986 if (decl.val.tag() == .extern_fn) {
1987 if (decl.val.getExternFunc(mod)) |_| {
19871988 return; // TODO Should we do more when front-end analyzed extern decl?
19881989 }
1989 if (decl.val.castTag(.variable)) |payload| {
1990 const variable = payload.data;
1990 if (decl.val.getVariable(mod)) |variable| {
19911991 if (variable.is_extern) {
19921992 return; // TODO Should we do more when front-end analyzed extern decl?
19931993 }
19941994 }
19951995
1996 const is_threadlocal = if (decl.val.castTag(.variable)) |payload|
1997 payload.data.is_threadlocal and !self.base.options.single_threaded
1996 const is_threadlocal = if (decl.val.getVariable(mod)) |variable|
1997 variable.is_threadlocal and !self.base.options.single_threaded
19981998 else
19991999 false;
2000 if (is_threadlocal) return self.updateThreadlocalVariable(module, decl_index);
2000 if (is_threadlocal) return self.updateThreadlocalVariable(mod, decl_index);
20012001
20022002 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
20032003 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;
......@@ -2007,14 +2007,14 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20072007 defer code_buffer.deinit();
20082008
20092009 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
2010 try d_sym.dwarf.initDeclState(module, decl_index)
2010 try d_sym.dwarf.initDeclState(mod, decl_index)
20112011 else
20122012 null;
20132013 defer if (decl_state) |*ds| ds.deinit();
20142014
2015 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2015 const decl_val = if (decl.val.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
20162016 const res = if (decl_state) |*ds|
2017 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2017 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
20182018 .ty = decl.ty,
20192019 .val = decl_val,
20202020 }, &code_buffer, .{
......@@ -2023,7 +2023,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20232023 .parent_atom_index = sym_index,
20242024 })
20252025 else
2026 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2026 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
20272027 .ty = decl.ty,
20282028 .val = decl_val,
20292029 }, &code_buffer, .none, .{
......@@ -2034,7 +2034,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20342034 .ok => code_buffer.items,
20352035 .fail => |em| {
20362036 decl.analysis = .codegen_failure;
2037 try module.failed_decls.put(module.gpa, decl_index, em);
2037 try mod.failed_decls.put(mod.gpa, decl_index, em);
20382038 return;
20392039 },
20402040 };
......@@ -2042,7 +2042,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20422042
20432043 if (decl_state) |*ds| {
20442044 try self.d_sym.?.dwarf.commitDeclState(
2045 module,
2045 mod,
20462046 decl_index,
20472047 addr,
20482048 self.getAtom(atom_index).size,
......@@ -2052,7 +2052,7 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
20522052
20532053 // Since we updated the vaddr and the size, each corresponding export symbol also
20542054 // needs to be updated.
2055 try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
2055 try self.updateDeclExports(mod, decl_index, mod.getDeclExports(decl_index));
20562056}
20572057
20582058fn updateLazySymbolAtom(
......@@ -2081,8 +2081,8 @@ fn updateLazySymbolAtom(
20812081 const atom = self.getAtomPtr(atom_index);
20822082 const local_sym_index = atom.getSymbolIndex().?;
20832083
2084 const src = if (sym.ty.getOwnerDeclOrNull()) |owner_decl|
2085 mod.declPtr(owner_decl).srcLoc()
2084 const src = if (sym.ty.getOwnerDeclOrNull(mod)) |owner_decl|
2085 mod.declPtr(owner_decl).srcLoc(mod)
20862086 else
20872087 Module.SrcLoc{
20882088 .file_scope = undefined,
......@@ -2126,7 +2126,8 @@ fn updateLazySymbolAtom(
21262126}
21272127
21282128pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index {
2129 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
2129 const mod = self.base.options.module.?;
2130 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl(mod));
21302131 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
21312132 if (!gop.found_existing) gop.value_ptr.* = .{};
21322133 const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
......@@ -2144,7 +2145,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
21442145 metadata.state.* = .pending_flush;
21452146 const atom = metadata.atom.*;
21462147 // anyerror needs to be deferred until flushModule
2147 if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
2148 if (sym.getDecl(mod) != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
21482149 .code => self.text_section_index.?,
21492150 .const_data => self.data_const_section_index.?,
21502151 });
......@@ -2152,6 +2153,7 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
21522153}
21532154
21542155fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void {
2156 const mod = self.base.options.module.?;
21552157 // Lowering a TLV on macOS involves two stages:
21562158 // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss)
21572159 // 2. next, we create a corresponding threadlocal variable descriptor in __thread_vars
......@@ -2175,9 +2177,9 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
21752177
21762178 const decl = module.declPtr(decl_index);
21772179 const decl_metadata = self.decls.get(decl_index).?;
2178 const decl_val = decl.val.castTag(.variable).?.data.init;
2180 const decl_val = decl.val.getVariable(mod).?.init.toValue();
21792181 const res = if (decl_state) |*ds|
2180 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2182 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
21812183 .ty = decl.ty,
21822184 .val = decl_val,
21832185 }, &code_buffer, .{
......@@ -2186,7 +2188,7 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
21862188 .parent_atom_index = init_sym_index,
21872189 })
21882190 else
2189 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2191 try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
21902192 .ty = decl.ty,
21912193 .val = decl_val,
21922194 }, &code_buffer, .none, .{
......@@ -2202,10 +2204,9 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
22022204 },
22032205 };
22042206
2205 const required_alignment = decl.getAlignment(self.base.options.target);
2207 const required_alignment = decl.getAlignment(mod);
22062208
2207 const decl_name = try decl.getFullyQualifiedName(module);
2208 defer gpa.free(decl_name);
2209 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(module));
22092210
22102211 const init_sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{decl_name});
22112212 defer gpa.free(init_sym_name);
......@@ -2262,12 +2263,13 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
22622263 const decl = self.base.options.module.?.declPtr(decl_index);
22632264 const ty = decl.ty;
22642265 const val = decl.val;
2265 const zig_ty = ty.zigTypeTag();
2266 const mod = self.base.options.module.?;
2267 const zig_ty = ty.zigTypeTag(mod);
22662268 const mode = self.base.options.optimize_mode;
22672269 const single_threaded = self.base.options.single_threaded;
22682270 const sect_id: u8 = blk: {
22692271 // TODO finish and audit this function
2270 if (val.isUndefDeep()) {
2272 if (val.isUndefDeep(mod)) {
22712273 if (mode == .ReleaseFast or mode == .ReleaseSmall) {
22722274 @panic("TODO __DATA,__bss");
22732275 } else {
......@@ -2275,8 +2277,8 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
22752277 }
22762278 }
22772279
2278 if (val.castTag(.variable)) |variable| {
2279 if (variable.data.is_threadlocal and !single_threaded) {
2280 if (val.getVariable(mod)) |variable| {
2281 if (variable.is_threadlocal and !single_threaded) {
22802282 break :blk self.thread_data_section_index.?;
22812283 }
22822284 break :blk self.data_section_index.?;
......@@ -2286,7 +2288,7 @@ fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
22862288 // TODO: what if this is a function pointer?
22872289 .Fn => break :blk self.text_section_index.?,
22882290 else => {
2289 if (val.castTag(.variable)) |_| {
2291 if (val.getVariable(mod)) |_| {
22902292 break :blk self.data_section_index.?;
22912293 }
22922294 break :blk self.data_const_section_index.?;
......@@ -2301,10 +2303,9 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
23012303 const mod = self.base.options.module.?;
23022304 const decl = mod.declPtr(decl_index);
23032305
2304 const required_alignment = decl.getAlignment(self.base.options.target);
2306 const required_alignment = decl.getAlignment(mod);
23052307
2306 const decl_name = try decl.getFullyQualifiedName(mod);
2307 defer gpa.free(decl_name);
2308 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
23082309
23092310 const decl_metadata = self.decls.get(decl_index).?;
23102311 const atom_index = decl_metadata.atom;
......@@ -2376,7 +2377,7 @@ pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: Module.De
23762377
23772378pub fn updateDeclExports(
23782379 self: *MachO,
2379 module: *Module,
2380 mod: *Module,
23802381 decl_index: Module.Decl.Index,
23812382 exports: []const *Module.Export,
23822383) File.UpdateDeclExportsError!void {
......@@ -2385,7 +2386,7 @@ pub fn updateDeclExports(
23852386 }
23862387 if (build_options.have_llvm) {
23872388 if (self.llvm_object) |llvm_object|
2388 return llvm_object.updateDeclExports(module, decl_index, exports);
2389 return llvm_object.updateDeclExports(mod, decl_index, exports);
23892390 }
23902391
23912392 const tracy = trace(@src());
......@@ -2393,26 +2394,28 @@ pub fn updateDeclExports(
23932394
23942395 const gpa = self.base.allocator;
23952396
2396 const decl = module.declPtr(decl_index);
2397 const decl = mod.declPtr(decl_index);
23972398 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
23982399 const atom = self.getAtom(atom_index);
23992400 const decl_sym = atom.getSymbol(self);
24002401 const decl_metadata = self.decls.getPtr(decl_index).?;
24012402
24022403 for (exports) |exp| {
2403 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name});
2404 const exp_name = try std.fmt.allocPrint(gpa, "_{}", .{
2405 exp.opts.name.fmt(&mod.intern_pool),
2406 });
24042407 defer gpa.free(exp_name);
24052408
24062409 log.debug("adding new export '{s}'", .{exp_name});
24072410
2408 if (exp.options.section) |section_name| {
2409 if (!mem.eql(u8, section_name, "__text")) {
2410 try module.failed_exports.putNoClobber(
2411 module.gpa,
2411 if (exp.opts.section.unwrap()) |section_name| {
2412 if (!mod.intern_pool.stringEqlSlice(section_name, "__text")) {
2413 try mod.failed_exports.putNoClobber(
2414 mod.gpa,
24122415 exp,
24132416 try Module.ErrorMsg.create(
24142417 gpa,
2415 decl.srcLoc(),
2418 decl.srcLoc(mod),
24162419 "Unimplemented: ExportOptions.section",
24172420 .{},
24182421 ),
......@@ -2421,13 +2424,13 @@ pub fn updateDeclExports(
24212424 }
24222425 }
24232426
2424 if (exp.options.linkage == .LinkOnce) {
2425 try module.failed_exports.putNoClobber(
2426 module.gpa,
2427 if (exp.opts.linkage == .LinkOnce) {
2428 try mod.failed_exports.putNoClobber(
2429 mod.gpa,
24272430 exp,
24282431 try Module.ErrorMsg.create(
24292432 gpa,
2430 decl.srcLoc(),
2433 decl.srcLoc(mod),
24312434 "Unimplemented: GlobalLinkage.LinkOnce",
24322435 .{},
24332436 ),
......@@ -2450,7 +2453,7 @@ pub fn updateDeclExports(
24502453 .n_value = decl_sym.n_value,
24512454 };
24522455
2453 switch (exp.options.linkage) {
2456 switch (exp.opts.linkage) {
24542457 .Internal => {
24552458 // Symbol should be hidden, or in MachO lingo, private extern.
24562459 // We should also mark the symbol as Weak: n_desc == N_WEAK_DEF.
......@@ -2471,9 +2474,9 @@ pub fn updateDeclExports(
24712474 // TODO: this needs rethinking
24722475 const global = self.getGlobal(exp_name).?;
24732476 if (sym_loc.sym_index != global.sym_index and global.file != null) {
2474 _ = try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(
2477 _ = try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(
24752478 gpa,
2476 decl.srcLoc(),
2479 decl.srcLoc(mod),
24772480 \\LinkError: symbol '{s}' defined multiple times
24782481 ,
24792482 .{exp_name},
......@@ -2485,12 +2488,17 @@ pub fn updateDeclExports(
24852488 }
24862489}
24872490
2488pub fn deleteDeclExport(self: *MachO, decl_index: Module.Decl.Index, name: []const u8) Allocator.Error!void {
2491pub fn deleteDeclExport(
2492 self: *MachO,
2493 decl_index: Module.Decl.Index,
2494 name: InternPool.NullTerminatedString,
2495) Allocator.Error!void {
24892496 if (self.llvm_object) |_| return;
24902497 const metadata = self.decls.getPtr(decl_index) orelse return;
24912498
24922499 const gpa = self.base.allocator;
2493 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});
2500 const mod = self.base.options.module.?;
2501 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{mod.intern_pool.stringToSlice(name)});
24942502 defer gpa.free(exp_name);
24952503 const sym_index = metadata.getExportPtr(self, exp_name) orelse return;
24962504
src/link/NvPtx.zig+2-2
......@@ -68,9 +68,9 @@ pub fn deinit(self: *NvPtx) void {
6868 self.base.allocator.free(self.ptx_file_name);
6969}
7070
71pub fn updateFunc(self: *NvPtx, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
71pub fn updateFunc(self: *NvPtx, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
7272 if (!build_options.have_llvm) return;
73 try self.llvm_object.updateFunc(module, func, air, liveness);
73 try self.llvm_object.updateFunc(module, func_index, air, liveness);
7474}
7575
7676pub fn updateDecl(self: *NvPtx, module: *Module, decl_index: Module.Decl.Index) !void {
src/link/Plan9.zig+39-46
......@@ -213,14 +213,14 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void {
213213 const gpa = self.base.allocator;
214214 const mod = self.base.options.module.?;
215215 const decl = mod.declPtr(decl_index);
216 const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope());
216 const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope(mod));
217217 if (fn_map_res.found_existing) {
218218 if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| {
219219 gpa.free(old_entry.value.code);
220220 gpa.free(old_entry.value.lineinfo);
221221 }
222222 } else {
223 const file = decl.getFileScope();
223 const file = decl.getFileScope(mod);
224224 const arena = self.path_arena.allocator();
225225 // each file gets a symbol
226226 fn_map_res.value_ptr.* = .{
......@@ -276,17 +276,17 @@ fn addPathComponents(self: *Plan9, path: []const u8, a: *std.ArrayList(u8)) !voi
276276 }
277277}
278278
279pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
279pub fn updateFunc(self: *Plan9, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
280280 if (build_options.skip_non_native and builtin.object_format != .plan9) {
281281 @panic("Attempted to compile for object format that was disabled by build configuration");
282282 }
283283
284 const func = mod.funcPtr(func_index);
284285 const decl_index = func.owner_decl;
285 const decl = module.declPtr(decl_index);
286 const decl = mod.declPtr(decl_index);
286287 self.freeUnnamedConsts(decl_index);
287288
288289 _ = try self.seeDecl(decl_index);
289 log.debug("codegen decl {*} ({s})", .{ decl, decl.name });
290290
291291 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
292292 defer code_buffer.deinit();
......@@ -298,8 +298,8 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
298298
299299 const res = try codegen.generateFunction(
300300 &self.base,
301 decl.srcLoc(),
302 func,
301 decl.srcLoc(mod),
302 func_index,
303303 air,
304304 liveness,
305305 &code_buffer,
......@@ -316,7 +316,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
316316 .ok => try code_buffer.toOwnedSlice(),
317317 .fail => |em| {
318318 decl.analysis = .codegen_failure;
319 try module.failed_decls.put(module.gpa, decl_index, em);
319 try mod.failed_decls.put(mod.gpa, decl_index, em);
320320 return;
321321 },
322322 };
......@@ -344,8 +344,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
344344 }
345345 const unnamed_consts = gop.value_ptr;
346346
347 const decl_name = try decl.getFullyQualifiedName(mod);
348 defer self.base.allocator.free(decl_name);
347 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
349348
350349 const index = unnamed_consts.items.len;
351350 // name is freed when the unnamed const is freed
......@@ -366,7 +365,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
366365 };
367366 self.syms.items[info.sym_index.?] = sym;
368367
369 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .{
368 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .{
370369 .none = {},
371370 }, .{
372371 .parent_atom_index = @enumToInt(decl_index),
......@@ -388,14 +387,13 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.I
388387 return @intCast(u32, info.got_index.?);
389388}
390389
391pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) !void {
392 const decl = module.declPtr(decl_index);
390pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: Module.Decl.Index) !void {
391 const decl = mod.declPtr(decl_index);
393392
394 if (decl.val.tag() == .extern_fn) {
393 if (decl.val.getExternFunc(mod)) |_| {
395394 return; // TODO Should we do more when front-end analyzed extern decl?
396395 }
397 if (decl.val.castTag(.variable)) |payload| {
398 const variable = payload.data;
396 if (decl.val.getVariable(mod)) |variable| {
399397 if (variable.is_extern) {
400398 return; // TODO Should we do more when front-end analyzed extern decl?
401399 }
......@@ -403,13 +401,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
403401
404402 _ = try self.seeDecl(decl_index);
405403
406 log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });
407
408404 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
409405 defer code_buffer.deinit();
410 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
406 const decl_val = if (decl.val.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
411407 // TODO we need the symbol index for symbol in the table of locals for the containing atom
412 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
408 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{
413409 .ty = decl.ty,
414410 .val = decl_val,
415411 }, &code_buffer, .{ .none = {} }, .{
......@@ -419,7 +415,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
419415 .ok => code_buffer.items,
420416 .fail => |em| {
421417 decl.analysis = .codegen_failure;
422 try module.failed_decls.put(module.gpa, decl_index, em);
418 try mod.failed_decls.put(mod.gpa, decl_index, em);
423419 return;
424420 },
425421 };
......@@ -432,9 +428,9 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
432428}
433429/// called at the end of update{Decl,Func}
434430fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void {
435 const decl = self.base.options.module.?.declPtr(decl_index);
436 const is_fn = (decl.ty.zigTypeTag() == .Fn);
437 log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name });
431 const mod = self.base.options.module.?;
432 const decl = mod.declPtr(decl_index);
433 const is_fn = (decl.ty.zigTypeTag(mod) == .Fn);
438434 const sym_t: aout.Sym.Type = if (is_fn) .t else .d;
439435
440436 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
......@@ -445,7 +441,7 @@ fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void {
445441 const sym: aout.Sym = .{
446442 .value = undefined, // the value of stuff gets filled in in flushModule
447443 .type = decl_block.type,
448 .name = mem.span(decl.name),
444 .name = try self.base.allocator.dupe(u8, mod.intern_pool.stringToSlice(decl.name)),
449445 };
450446
451447 if (decl_block.sym_index) |s| {
......@@ -566,10 +562,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
566562 var it = fentry.value_ptr.functions.iterator();
567563 while (it.next()) |entry| {
568564 const decl_index = entry.key_ptr.*;
569 const decl = mod.declPtr(decl_index);
570565 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
571566 const out = entry.value_ptr.*;
572 log.debug("write text decl {*} ({s}), lines {d} to {d}", .{ decl, decl.name, out.start_line + 1, out.end_line });
573567 {
574568 // connect the previous decl to the next
575569 const delta_line = @intCast(i32, out.start_line) - @intCast(i32, linecount);
......@@ -615,10 +609,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
615609 var it = self.data_decl_table.iterator();
616610 while (it.next()) |entry| {
617611 const decl_index = entry.key_ptr.*;
618 const decl = mod.declPtr(decl_index);
619612 const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
620613 const code = entry.value_ptr.*;
621 log.debug("write data decl {*} ({s})", .{ decl, decl.name });
622614
623615 foff += code.len;
624616 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };
......@@ -694,19 +686,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
694686 const source_decl = mod.declPtr(source_decl_index);
695687 for (kv.value_ptr.items) |reloc| {
696688 const target_decl_index = reloc.target;
697 const target_decl = mod.declPtr(target_decl_index);
698689 const target_decl_block = self.getDeclBlock(self.decls.get(target_decl_index).?.index);
699690 const target_decl_offset = target_decl_block.offset.?;
700691
701692 const offset = reloc.offset;
702693 const addend = reloc.addend;
703694
704 log.debug("relocating the address of '{s}' + {d} into '{s}' + {d}", .{ target_decl.name, addend, source_decl.name, offset });
705
706695 const code = blk: {
707 const is_fn = source_decl.ty.zigTypeTag() == .Fn;
696 const is_fn = source_decl.ty.zigTypeTag(mod) == .Fn;
708697 if (is_fn) {
709 const table = self.fn_decl_table.get(source_decl.getFileScope()).?.functions;
698 const table = self.fn_decl_table.get(source_decl.getFileScope(mod)).?.functions;
710699 const output = table.get(source_decl_index).?;
711700 break :blk output.code;
712701 } else {
......@@ -728,7 +717,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
728717}
729718fn addDeclExports(
730719 self: *Plan9,
731 module: *Module,
720 mod: *Module,
732721 decl_index: Module.Decl.Index,
733722 exports: []const *Module.Export,
734723) !void {
......@@ -736,12 +725,13 @@ fn addDeclExports(
736725 const decl_block = self.getDeclBlock(metadata.index);
737726
738727 for (exports) |exp| {
728 const exp_name = mod.intern_pool.stringToSlice(exp.opts.name);
739729 // plan9 does not support custom sections
740 if (exp.options.section) |section_name| {
741 if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) {
742 try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(
730 if (exp.opts.section.unwrap()) |section_name| {
731 if (!mod.intern_pool.stringEqlSlice(section_name, ".text") and !mod.intern_pool.stringEqlSlice(section_name, ".data")) {
732 try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(
743733 self.base.allocator,
744 module.declPtr(decl_index).srcLoc(),
734 mod.declPtr(decl_index).srcLoc(mod),
745735 "plan9 does not support extra sections",
746736 .{},
747737 ));
......@@ -751,10 +741,10 @@ fn addDeclExports(
751741 const sym = .{
752742 .value = decl_block.offset.?,
753743 .type = decl_block.type.toGlobal(),
754 .name = exp.options.name,
744 .name = try self.base.allocator.dupe(u8, exp_name),
755745 };
756746
757 if (metadata.getExport(self, exp.options.name)) |i| {
747 if (metadata.getExport(self, exp_name)) |i| {
758748 self.syms.items[i] = sym;
759749 } else {
760750 try self.syms.append(self.base.allocator, sym);
......@@ -770,9 +760,9 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
770760 // in the deleteUnusedDecl function.
771761 const mod = self.base.options.module.?;
772762 const decl = mod.declPtr(decl_index);
773 const is_fn = (decl.val.tag() == .function);
763 const is_fn = decl.val.getFunctionIndex(mod) != .none;
774764 if (is_fn) {
775 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?;
765 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope(mod)).?;
776766 var submap = symidx_and_submap.functions;
777767 if (submap.fetchSwapRemove(decl_index)) |removed_entry| {
778768 self.base.allocator.free(removed_entry.value.code);
......@@ -955,7 +945,10 @@ pub fn writeSym(self: *Plan9, w: anytype, sym: aout.Sym) !void {
955945 try w.writeAll(sym.name);
956946 try w.writeByte(0);
957947}
948
958949pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
950 const mod = self.base.options.module.?;
951 const ip = &mod.intern_pool;
959952 const writer = buf.writer();
960953 // write the f symbols
961954 {
......@@ -979,7 +972,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
979972 const sym = self.syms.items[decl_block.sym_index.?];
980973 try self.writeSym(writer, sym);
981974 if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {
982 for (exports.items) |e| if (decl_metadata.getExport(self, e.options.name)) |exp_i| {
975 for (exports.items) |e| if (decl_metadata.getExport(self, ip.stringToSlice(e.opts.name))) |exp_i| {
983976 try self.writeSym(writer, self.syms.items[exp_i]);
984977 };
985978 }
......@@ -1005,7 +998,7 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
1005998 const sym = self.syms.items[decl_block.sym_index.?];
1006999 try self.writeSym(writer, sym);
10071000 if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {
1008 for (exports.items) |e| if (decl_metadata.getExport(self, e.options.name)) |exp_i| {
1001 for (exports.items) |e| if (decl_metadata.getExport(self, ip.stringToSlice(e.opts.name))) |exp_i| {
10091002 const s = self.syms.items[exp_i];
10101003 if (mem.eql(u8, s.name, "_start"))
10111004 self.entry_val = s.value;
......@@ -1031,7 +1024,7 @@ pub fn getDeclVAddr(
10311024) !u64 {
10321025 const mod = self.base.options.module.?;
10331026 const decl = mod.declPtr(decl_index);
1034 if (decl.ty.zigTypeTag() == .Fn) {
1027 if (decl.ty.zigTypeTag(mod) == .Fn) {
10351028 var start = self.bases.text;
10361029 var it_file = self.fn_decl_table.iterator();
10371030 while (it_file.next()) |fentry| {
src/link/SpirV.zig+9-6
......@@ -103,11 +103,13 @@ pub fn deinit(self: *SpirV) void {
103103 self.decl_link.deinit();
104104}
105105
106pub fn updateFunc(self: *SpirV, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
106pub fn updateFunc(self: *SpirV, module: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
107107 if (build_options.skip_non_native) {
108108 @panic("Attempted to compile for architecture that was disabled by build configuration");
109109 }
110110
111 const func = module.funcPtr(func_index);
112
111113 var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &self.spv, &self.decl_link);
112114 defer decl_gen.deinit();
113115
......@@ -131,12 +133,12 @@ pub fn updateDecl(self: *SpirV, module: *Module, decl_index: Module.Decl.Index)
131133
132134pub fn updateDeclExports(
133135 self: *SpirV,
134 module: *Module,
136 mod: *Module,
135137 decl_index: Module.Decl.Index,
136138 exports: []const *Module.Export,
137139) !void {
138 const decl = module.declPtr(decl_index);
139 if (decl.val.tag() == .function and decl.ty.fnCallingConvention() == .Kernel) {
140 const decl = mod.declPtr(decl_index);
141 if (decl.val.getFunctionIndex(mod) != .none and decl.ty.fnCallingConvention(mod) == .Kernel) {
140142 // TODO: Unify with resolveDecl in spirv.zig.
141143 const entry = try self.decl_link.getOrPut(decl_index);
142144 if (!entry.found_existing) {
......@@ -145,7 +147,7 @@ pub fn updateDeclExports(
145147 const spv_decl_index = entry.value_ptr.*;
146148
147149 for (exports) |exp| {
148 try self.spv.declareEntryPoint(spv_decl_index, exp.options.name);
150 try self.spv.declareEntryPoint(spv_decl_index, mod.intern_pool.stringToSlice(exp.opts.name));
149151 }
150152 }
151153
......@@ -188,7 +190,8 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
188190 var error_info = std.ArrayList(u8).init(self.spv.arena);
189191 try error_info.appendSlice("zig_errors");
190192 const module = self.base.options.module.?;
191 for (module.error_name_list.items) |name| {
193 for (module.global_error_set.keys()) |name_nts| {
194 const name = module.intern_pool.stringToSlice(name_nts);
192195 // Errors can contain pretty much any character - to encode them in a string we must escape
193196 // them somehow. Easiest here is to use some established scheme, one which also preseves the
194197 // name if it contains no strange characters is nice for debugging. URI encoding fits the bill.
src/link/Wasm.zig+96-79
......@@ -149,7 +149,8 @@ discarded: std.AutoHashMapUnmanaged(SymbolLoc, SymbolLoc) = .{},
149149/// into the final binary.
150150resolved_symbols: std.AutoArrayHashMapUnmanaged(SymbolLoc, void) = .{},
151151/// Symbols that remain undefined after symbol resolution.
152undefs: std.StringArrayHashMapUnmanaged(SymbolLoc) = .{},
152/// Note: The key represents an offset into the string table, rather than the actual string.
153undefs: std.AutoArrayHashMapUnmanaged(u32, SymbolLoc) = .{},
153154/// Maps a symbol's location to an atom. This can be used to find meta
154155/// data of a symbol, such as its size, or its offset to perform a relocation.
155156/// Undefined (and synthetic) symbols do not have an Atom and therefore cannot be mapped.
......@@ -514,6 +515,10 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Wasm {
514515/// Leaves index undefined and the default flags (0).
515516fn createSyntheticSymbol(wasm: *Wasm, name: []const u8, tag: Symbol.Tag) !SymbolLoc {
516517 const name_offset = try wasm.string_table.put(wasm.base.allocator, name);
518 return wasm.createSyntheticSymbolOffset(name_offset, tag);
519}
520
521fn createSyntheticSymbolOffset(wasm: *Wasm, name_offset: u32, tag: Symbol.Tag) !SymbolLoc {
517522 const sym_index = @intCast(u32, wasm.symbols.items.len);
518523 const loc: SymbolLoc = .{ .index = sym_index, .file = null };
519524 try wasm.symbols.append(wasm.base.allocator, .{
......@@ -691,7 +696,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
691696 try wasm.resolved_symbols.putNoClobber(wasm.base.allocator, location, {});
692697
693698 if (symbol.isUndefined()) {
694 try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name, location);
699 try wasm.undefs.putNoClobber(wasm.base.allocator, sym_name_index, location);
695700 }
696701 continue;
697702 }
......@@ -801,7 +806,7 @@ fn resolveSymbolsInObject(wasm: *Wasm, object_index: u16) !void {
801806 try wasm.resolved_symbols.put(wasm.base.allocator, location, {});
802807 assert(wasm.resolved_symbols.swapRemove(existing_loc));
803808 if (existing_sym.isUndefined()) {
804 _ = wasm.undefs.swapRemove(sym_name);
809 _ = wasm.undefs.swapRemove(sym_name_index);
805810 }
806811 }
807812}
......@@ -812,15 +817,16 @@ fn resolveSymbolsInArchives(wasm: *Wasm) !void {
812817 log.debug("Resolving symbols in archives", .{});
813818 var index: u32 = 0;
814819 undef_loop: while (index < wasm.undefs.count()) {
815 const sym_name = wasm.undefs.keys()[index];
820 const sym_name_index = wasm.undefs.keys()[index];
816821
817822 for (wasm.archives.items) |archive| {
823 const sym_name = wasm.string_table.get(sym_name_index);
824 log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name });
818825 const offset = archive.toc.get(sym_name) orelse {
819826 // symbol does not exist in this archive
820827 continue;
821828 };
822829
823 log.debug("Detected symbol '{s}' in archive '{s}', parsing objects..", .{ sym_name, archive.name });
824830 // Symbol is found in unparsed object file within current archive.
825831 // Parse object and and resolve symbols again before we check remaining
826832 // undefined symbols.
......@@ -1191,28 +1197,36 @@ fn validateFeatures(
11911197/// if one or multiple undefined references exist. When none exist, the symbol will
11921198/// not be created, ensuring we don't unneccesarily emit unreferenced symbols.
11931199fn resolveLazySymbols(wasm: *Wasm) !void {
1194 if (wasm.undefs.fetchSwapRemove("__heap_base")) |kv| {
1195 const loc = try wasm.createSyntheticSymbol("__heap_base", .data);
1196 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1197 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.
1200 if (wasm.string_table.getOffset("__heap_base")) |name_offset| {
1201 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1202 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1203 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1204 _ = wasm.resolved_symbols.swapRemove(loc); // we don't want to emit this symbol, only use it for relocations.
1205 }
11981206 }
11991207
1200 if (wasm.undefs.fetchSwapRemove("__heap_end")) |kv| {
1201 const loc = try wasm.createSyntheticSymbol("__heap_end", .data);
1202 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1203 _ = wasm.resolved_symbols.swapRemove(loc);
1208 if (wasm.string_table.getOffset("__heap_end")) |name_offset| {
1209 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1210 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1211 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1212 _ = wasm.resolved_symbols.swapRemove(loc);
1213 }
12041214 }
12051215
12061216 if (!wasm.base.options.shared_memory) {
1207 if (wasm.undefs.fetchSwapRemove("__tls_base")) |kv| {
1208 const loc = try wasm.createSyntheticSymbol("__tls_base", .global);
1209 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1217 if (wasm.string_table.getOffset("__tls_base")) |name_offset| {
1218 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1219 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .global);
1220 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1221 }
12101222 }
12111223 }
1212 if (wasm.undefs.fetchSwapRemove("__zig_errors_len")) |kv| {
1213 const loc = try wasm.createSyntheticSymbol("__zig_errors_len", .data);
1214 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1215 _ = wasm.resolved_symbols.swapRemove(kv.value);
1224 if (wasm.string_table.getOffset("__zig_errors_len")) |name_offset| {
1225 if (wasm.undefs.fetchSwapRemove(name_offset)) |kv| {
1226 const loc = try wasm.createSyntheticSymbolOffset(name_offset, .data);
1227 try wasm.discarded.putNoClobber(wasm.base.allocator, kv.value, loc);
1228 _ = wasm.resolved_symbols.swapRemove(kv.value);
1229 }
12161230 }
12171231}
12181232
......@@ -1324,17 +1338,18 @@ pub fn allocateSymbol(wasm: *Wasm) !u32 {
13241338 return index;
13251339}
13261340
1327pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1341pub fn updateFunc(wasm: *Wasm, mod: *Module, func_index: Module.Fn.Index, air: Air, liveness: Liveness) !void {
13281342 if (build_options.skip_non_native and builtin.object_format != .wasm) {
13291343 @panic("Attempted to compile for object format that was disabled by build configuration");
13301344 }
13311345 if (build_options.have_llvm) {
1332 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func, air, liveness);
1346 if (wasm.llvm_object) |llvm_object| return llvm_object.updateFunc(mod, func_index, air, liveness);
13331347 }
13341348
13351349 const tracy = trace(@src());
13361350 defer tracy.end();
13371351
1352 const func = mod.funcPtr(func_index);
13381353 const decl_index = func.owner_decl;
13391354 const decl = mod.declPtr(decl_index);
13401355 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
......@@ -1348,7 +1363,7 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
13481363 defer code_writer.deinit();
13491364 // const result = try codegen.generateFunction(
13501365 // &wasm.base,
1351 // decl.srcLoc(),
1366 // decl.srcLoc(mod),
13521367 // func,
13531368 // air,
13541369 // liveness,
......@@ -1357,8 +1372,8 @@ pub fn updateFunc(wasm: *Wasm, mod: *Module, func: *Module.Fn, air: Air, livenes
13571372 // );
13581373 const result = try codegen.generateFunction(
13591374 &wasm.base,
1360 decl.srcLoc(),
1361 func,
1375 decl.srcLoc(mod),
1376 func_index,
13621377 air,
13631378 liveness,
13641379 &code_writer,
......@@ -1403,9 +1418,9 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
14031418 defer tracy.end();
14041419
14051420 const decl = mod.declPtr(decl_index);
1406 if (decl.val.castTag(.function)) |_| {
1421 if (decl.val.getFunction(mod)) |_| {
14071422 return;
1408 } else if (decl.val.castTag(.extern_fn)) |_| {
1423 } else if (decl.val.getExternFunc(mod)) |_| {
14091424 return;
14101425 }
14111426
......@@ -1413,19 +1428,20 @@ pub fn updateDecl(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.Index) !voi
14131428 const atom = wasm.getAtomPtr(atom_index);
14141429 atom.clear();
14151430
1416 if (decl.isExtern()) {
1417 const variable = decl.getVariable().?;
1418 const name = mem.sliceTo(decl.name, 0);
1419 return wasm.addOrUpdateImport(name, atom.sym_index, variable.lib_name, null);
1431 if (decl.isExtern(mod)) {
1432 const variable = decl.getOwnedVariable(mod).?;
1433 const name = mod.intern_pool.stringToSlice(decl.name);
1434 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
1435 return wasm.addOrUpdateImport(name, atom.sym_index, lib_name, null);
14201436 }
1421 const val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
1437 const val = if (decl.val.getVariable(mod)) |variable| variable.init.toValue() else decl.val;
14221438
14231439 var code_writer = std.ArrayList(u8).init(wasm.base.allocator);
14241440 defer code_writer.deinit();
14251441
14261442 const res = try codegen.generateSymbol(
14271443 &wasm.base,
1428 decl.srcLoc(),
1444 decl.srcLoc(mod),
14291445 .{ .ty = decl.ty, .val = val },
14301446 &code_writer,
14311447 .none,
......@@ -1451,8 +1467,7 @@ pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Module, decl_index: Module.Decl.I
14511467 defer tracy.end();
14521468
14531469 const decl = mod.declPtr(decl_index);
1454 const decl_name = try decl.getFullyQualifiedName(mod);
1455 defer wasm.base.allocator.free(decl_name);
1470 const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
14561471
14571472 log.debug("updateDeclLineNumber {s}{*}", .{ decl_name, decl });
14581473 try dw.updateDeclLineNumber(mod, decl_index);
......@@ -1465,15 +1480,14 @@ fn finishUpdateDecl(wasm: *Wasm, decl_index: Module.Decl.Index, code: []const u8
14651480 const atom_index = wasm.decls.get(decl_index).?;
14661481 const atom = wasm.getAtomPtr(atom_index);
14671482 const symbol = &wasm.symbols.items[atom.sym_index];
1468 const full_name = try decl.getFullyQualifiedName(mod);
1469 defer wasm.base.allocator.free(full_name);
1483 const full_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
14701484 symbol.name = try wasm.string_table.put(wasm.base.allocator, full_name);
14711485 try atom.code.appendSlice(wasm.base.allocator, code);
14721486 try wasm.resolved_symbols.put(wasm.base.allocator, atom.symbolLoc(), {});
14731487
14741488 atom.size = @intCast(u32, code.len);
14751489 if (code.len == 0) return;
1476 atom.alignment = decl.ty.abiAlignment(wasm.base.options.target);
1490 atom.alignment = decl.ty.abiAlignment(mod);
14771491}
14781492
14791493/// From a given symbol location, returns its `wasm.GlobalType`.
......@@ -1523,9 +1537,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type {
15231537/// Returns the symbol index of the local
15241538/// The given `decl` is the parent decl whom owns the constant.
15251539pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
1526 assert(tv.ty.zigTypeTag() != .Fn); // cannot create local symbols for functions
1527
15281540 const mod = wasm.base.options.module.?;
1541 assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions
15291542 const decl = mod.declPtr(decl_index);
15301543
15311544 // Create and initialize a new local symbol and atom
......@@ -1534,16 +1547,17 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
15341547 const parent_atom = wasm.getAtomPtr(parent_atom_index);
15351548 const local_index = parent_atom.locals.items.len;
15361549 try parent_atom.locals.append(wasm.base.allocator, atom_index);
1537 const fqdn = try decl.getFullyQualifiedName(mod);
1538 defer wasm.base.allocator.free(fqdn);
1539 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{ fqdn, local_index });
1550 const fqn = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
1551 const name = try std.fmt.allocPrintZ(wasm.base.allocator, "__unnamed_{s}_{d}", .{
1552 fqn, local_index,
1553 });
15401554 defer wasm.base.allocator.free(name);
15411555 var value_bytes = std.ArrayList(u8).init(wasm.base.allocator);
15421556 defer value_bytes.deinit();
15431557
15441558 const code = code: {
15451559 const atom = wasm.getAtomPtr(atom_index);
1546 atom.alignment = tv.ty.abiAlignment(wasm.base.options.target);
1560 atom.alignment = tv.ty.abiAlignment(mod);
15471561 wasm.symbols.items[atom.sym_index] = .{
15481562 .name = try wasm.string_table.put(wasm.base.allocator, name),
15491563 .flags = @enumToInt(Symbol.Flag.WASM_SYM_BINDING_LOCAL),
......@@ -1555,7 +1569,7 @@ pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: Module.Decl.In
15551569
15561570 const result = try codegen.generateSymbol(
15571571 &wasm.base,
1558 decl.srcLoc(),
1572 decl.srcLoc(mod),
15591573 tv,
15601574 &value_bytes,
15611575 .none,
......@@ -1611,7 +1625,7 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !u3
16111625 wasm.symbols.items[sym_index] = symbol;
16121626 gop.value_ptr.* = .{ .index = sym_index, .file = null };
16131627 try wasm.resolved_symbols.put(wasm.base.allocator, gop.value_ptr.*, {});
1614 try wasm.undefs.putNoClobber(wasm.base.allocator, name, gop.value_ptr.*);
1628 try wasm.undefs.putNoClobber(wasm.base.allocator, name_index, gop.value_ptr.*);
16151629 return sym_index;
16161630}
16171631
......@@ -1632,7 +1646,7 @@ pub fn getDeclVAddr(
16321646 const atom_index = wasm.symbol_atom.get(.{ .file = null, .index = reloc_info.parent_atom_index }).?;
16331647 const atom = wasm.getAtomPtr(atom_index);
16341648 const is_wasm32 = wasm.base.options.target.cpu.arch == .wasm32;
1635 if (decl.ty.zigTypeTag() == .Fn) {
1649 if (decl.ty.zigTypeTag(mod) == .Fn) {
16361650 assert(reloc_info.addend == 0); // addend not allowed for function relocations
16371651 // We found a function pointer, so add it to our table,
16381652 // as function pointers are not allowed to be stored inside the data section.
......@@ -1689,36 +1703,37 @@ pub fn updateDeclExports(
16891703 const decl = mod.declPtr(decl_index);
16901704 const atom_index = try wasm.getOrCreateAtomForDecl(decl_index);
16911705 const atom = wasm.getAtom(atom_index);
1706 const gpa = mod.gpa;
16921707
16931708 for (exports) |exp| {
1694 if (exp.options.section) |section| {
1695 try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create(
1696 mod.gpa,
1697 decl.srcLoc(),
1709 if (mod.intern_pool.stringToSliceUnwrap(exp.opts.section)) |section| {
1710 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(
1711 gpa,
1712 decl.srcLoc(mod),
16981713 "Unimplemented: ExportOptions.section '{s}'",
16991714 .{section},
17001715 ));
17011716 continue;
17021717 }
17031718
1704 const export_name = try wasm.string_table.put(wasm.base.allocator, exp.options.name);
1719 const export_name = try wasm.string_table.put(wasm.base.allocator, mod.intern_pool.stringToSlice(exp.opts.name));
17051720 if (wasm.globals.getPtr(export_name)) |existing_loc| {
17061721 if (existing_loc.index == atom.sym_index) continue;
17071722 const existing_sym: Symbol = existing_loc.getSymbol(wasm).*;
17081723
1709 const exp_is_weak = exp.options.linkage == .Internal or exp.options.linkage == .Weak;
1724 const exp_is_weak = exp.opts.linkage == .Internal or exp.opts.linkage == .Weak;
17101725 // When both the to-be-exported symbol and the already existing symbol
17111726 // are strong symbols, we have a linker error.
17121727 // In the other case we replace one with the other.
17131728 if (!exp_is_weak and !existing_sym.isWeak()) {
1714 try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(
1715 mod.gpa,
1716 decl.srcLoc(),
1717 \\LinkError: symbol '{s}' defined multiple times
1729 try mod.failed_exports.put(gpa, exp, try Module.ErrorMsg.create(
1730 gpa,
1731 decl.srcLoc(mod),
1732 \\LinkError: symbol '{}' defined multiple times
17181733 \\ first definition in '{s}'
17191734 \\ next definition in '{s}'
17201735 ,
1721 .{ exp.options.name, wasm.name, wasm.name },
1736 .{ exp.opts.name.fmt(&mod.intern_pool), wasm.name, wasm.name },
17221737 ));
17231738 continue;
17241739 } else if (exp_is_weak) {
......@@ -1735,7 +1750,7 @@ pub fn updateDeclExports(
17351750 const exported_atom = wasm.getAtom(exported_atom_index);
17361751 const sym_loc = exported_atom.symbolLoc();
17371752 const symbol = sym_loc.getSymbol(wasm);
1738 switch (exp.options.linkage) {
1753 switch (exp.opts.linkage) {
17391754 .Internal => {
17401755 symbol.setFlag(.WASM_SYM_VISIBILITY_HIDDEN);
17411756 },
......@@ -1744,9 +1759,9 @@ pub fn updateDeclExports(
17441759 },
17451760 .Strong => {}, // symbols are strong by default
17461761 .LinkOnce => {
1747 try mod.failed_exports.putNoClobber(mod.gpa, exp, try Module.ErrorMsg.create(
1748 mod.gpa,
1749 decl.srcLoc(),
1762 try mod.failed_exports.putNoClobber(gpa, exp, try Module.ErrorMsg.create(
1763 gpa,
1764 decl.srcLoc(mod),
17501765 "Unimplemented: LinkOnce",
17511766 .{},
17521767 ));
......@@ -1754,7 +1769,7 @@ pub fn updateDeclExports(
17541769 },
17551770 }
17561771 // Ensure the symbol will be exported using the given name
1757 if (!mem.eql(u8, exp.options.name, sym_loc.getName(wasm))) {
1772 if (!mod.intern_pool.stringEqlSlice(exp.opts.name, sym_loc.getName(wasm))) {
17581773 try wasm.export_names.put(wasm.base.allocator, sym_loc, export_name);
17591774 }
17601775
......@@ -1768,7 +1783,7 @@ pub fn updateDeclExports(
17681783
17691784 // if the symbol was previously undefined, remove it as an import
17701785 _ = wasm.imports.remove(sym_loc);
1771 _ = wasm.undefs.swapRemove(exp.options.name);
1786 _ = wasm.undefs.swapRemove(export_name);
17721787 }
17731788}
17741789
......@@ -1792,7 +1807,7 @@ pub fn freeDecl(wasm: *Wasm, decl_index: Module.Decl.Index) void {
17921807 assert(wasm.symbol_atom.remove(local_atom.symbolLoc()));
17931808 }
17941809
1795 if (decl.isExtern()) {
1810 if (decl.isExtern(mod)) {
17961811 _ = wasm.imports.remove(atom.symbolLoc());
17971812 }
17981813 _ = wasm.resolved_symbols.swapRemove(atom.symbolLoc());
......@@ -1853,7 +1868,7 @@ pub fn addOrUpdateImport(
18531868 /// Symbol index that is external
18541869 symbol_index: u32,
18551870 /// Optional library name (i.e. `extern "c" fn foo() void`
1856 lib_name: ?[*:0]const u8,
1871 lib_name: ?[:0]const u8,
18571872 /// The index of the type that represents the function signature
18581873 /// when the extern is a function. When this is null, a data-symbol
18591874 /// is asserted instead.
......@@ -1864,7 +1879,7 @@ pub fn addOrUpdateImport(
18641879 // Also mangle the name when the lib name is set and not equal to "C" so imports with the same
18651880 // name but different module can be resolved correctly.
18661881 const mangle_name = lib_name != null and
1867 !std.mem.eql(u8, std.mem.sliceTo(lib_name.?, 0), "c");
1882 !std.mem.eql(u8, lib_name.?, "c");
18681883 const full_name = if (mangle_name) full_name: {
18691884 break :full_name try std.fmt.allocPrint(wasm.base.allocator, "{s}|{s}", .{ name, lib_name.? });
18701885 } else name;
......@@ -1884,13 +1899,13 @@ pub fn addOrUpdateImport(
18841899 const loc: SymbolLoc = .{ .file = null, .index = symbol_index };
18851900 global_gop.value_ptr.* = loc;
18861901 try wasm.resolved_symbols.put(wasm.base.allocator, loc, {});
1887 try wasm.undefs.putNoClobber(wasm.base.allocator, full_name, loc);
1902 try wasm.undefs.putNoClobber(wasm.base.allocator, decl_name_index, loc);
18881903 }
18891904
18901905 if (type_index) |ty_index| {
18911906 const gop = try wasm.imports.getOrPut(wasm.base.allocator, .{ .index = symbol_index, .file = null });
18921907 const module_name = if (lib_name) |l_name| blk: {
1893 break :blk mem.sliceTo(l_name, 0);
1908 break :blk l_name;
18941909 } else wasm.host_name;
18951910 if (!gop.found_existing) {
18961911 gop.value_ptr.* = .{
......@@ -2932,8 +2947,9 @@ pub fn getErrorTableSymbol(wasm: *Wasm) !u32 {
29322947
29332948 const atom_index = try wasm.createAtom();
29342949 const atom = wasm.getAtomPtr(atom_index);
2935 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
2936 atom.alignment = slice_ty.abiAlignment(wasm.base.options.target);
2950 const slice_ty = Type.slice_const_u8_sentinel_0;
2951 const mod = wasm.base.options.module.?;
2952 atom.alignment = slice_ty.abiAlignment(mod);
29372953 const sym_index = atom.sym_index;
29382954
29392955 const sym_name = try wasm.string_table.put(wasm.base.allocator, "__zig_err_name_table");
......@@ -2985,10 +3001,11 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
29853001 // Addend for each relocation to the table
29863002 var addend: u32 = 0;
29873003 const mod = wasm.base.options.module.?;
2988 for (mod.error_name_list.items) |error_name| {
3004 for (mod.global_error_set.keys()) |error_name_nts| {
3005 const error_name = mod.intern_pool.stringToSlice(error_name_nts);
29893006 const len = @intCast(u32, error_name.len + 1); // names are 0-termianted
29903007
2991 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
3008 const slice_ty = Type.slice_const_u8_sentinel_0;
29923009 const offset = @intCast(u32, atom.code.items.len);
29933010 // first we create the data for the slice of the name
29943011 try atom.code.appendNTimes(wasm.base.allocator, 0, 4); // ptr to name, will be relocated
......@@ -3000,7 +3017,7 @@ fn populateErrorNameTable(wasm: *Wasm) !void {
30003017 .offset = offset,
30013018 .addend = @intCast(i32, addend),
30023019 });
3003 atom.size += @intCast(u32, slice_ty.abiSize(wasm.base.options.target));
3020 atom.size += @intCast(u32, slice_ty.abiSize(mod));
30043021 addend += len;
30053022
30063023 // as we updated the error name table, we now store the actual name within the names atom
......@@ -3366,15 +3383,15 @@ pub fn flushModule(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Nod
33663383 var decl_it = wasm.decls.iterator();
33673384 while (decl_it.next()) |entry| {
33683385 const decl = mod.declPtr(entry.key_ptr.*);
3369 if (decl.isExtern()) continue;
3386 if (decl.isExtern(mod)) continue;
33703387 const atom_index = entry.value_ptr.*;
33713388 const atom = wasm.getAtomPtr(atom_index);
3372 if (decl.ty.zigTypeTag() == .Fn) {
3389 if (decl.ty.zigTypeTag(mod) == .Fn) {
33733390 try wasm.parseAtom(atom_index, .function);
3374 } else if (decl.getVariable()) |variable| {
3375 if (!variable.is_mutable) {
3391 } else if (decl.getOwnedVariable(mod)) |variable| {
3392 if (variable.is_const) {
33763393 try wasm.parseAtom(atom_index, .{ .data = .read_only });
3377 } else if (variable.init.isUndefDeep()) {
3394 } else if (variable.init.toValue().isUndefDeep(mod)) {
33783395 // for safe build modes, we store the atom in the data segment,
33793396 // whereas for unsafe build modes we store it in bss.
33803397 const is_initialized = wasm.base.options.optimize_mode == .Debug or
src/main.zig+5
......@@ -569,6 +569,7 @@ const usage_build_generic =
569569 \\ --verbose-link Display linker invocations
570570 \\ --verbose-cc Display C compiler invocations
571571 \\ --verbose-air Enable compiler debug output for Zig AIR
572 \\ --verbose-intern-pool Enable compiler debug output for InternPool
572573 \\ --verbose-llvm-ir[=path] Enable compiler debug output for unoptimized LLVM IR
573574 \\ --verbose-llvm-bc=[path] Enable compiler debug output for unoptimized LLVM BC
574575 \\ --verbose-cimport Enable compiler debug output for C imports
......@@ -735,6 +736,7 @@ fn buildOutputType(
735736 var verbose_link = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_LINK");
736737 var verbose_cc = (builtin.os.tag != .wasi or builtin.link_libc) and std.process.hasEnvVarConstant("ZIG_VERBOSE_CC");
737738 var verbose_air = false;
739 var verbose_intern_pool = false;
738740 var verbose_llvm_ir: ?[]const u8 = null;
739741 var verbose_llvm_bc: ?[]const u8 = null;
740742 var verbose_cimport = false;
......@@ -1460,6 +1462,8 @@ fn buildOutputType(
14601462 verbose_cc = true;
14611463 } else if (mem.eql(u8, arg, "--verbose-air")) {
14621464 verbose_air = true;
1465 } else if (mem.eql(u8, arg, "--verbose-intern-pool")) {
1466 verbose_intern_pool = true;
14631467 } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
14641468 verbose_llvm_ir = "-";
14651469 } else if (mem.startsWith(u8, arg, "--verbose-llvm-ir=")) {
......@@ -3156,6 +3160,7 @@ fn buildOutputType(
31563160 .verbose_cc = verbose_cc,
31573161 .verbose_link = verbose_link,
31583162 .verbose_air = verbose_air,
3163 .verbose_intern_pool = verbose_intern_pool,
31593164 .verbose_llvm_ir = verbose_llvm_ir,
31603165 .verbose_llvm_bc = verbose_llvm_bc,
31613166 .verbose_cimport = verbose_cimport,
src/print_air.zig+32-37
......@@ -7,6 +7,7 @@ const Value = @import("value.zig").Value;
77const Type = @import("type.zig").Type;
88const Air = @import("Air.zig");
99const Liveness = @import("Liveness.zig");
10const InternPool = @import("InternPool.zig");
1011
1112pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) void {
1213 const instruction_bytes = air.instructions.len *
......@@ -14,12 +15,11 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
1415 // the debug safety tag but we want to measure release size.
1516 (@sizeOf(Air.Inst.Tag) + 8);
1617 const extra_bytes = air.extra.len * @sizeOf(u32);
17 const values_bytes = air.values.len * @sizeOf(Value);
1818 const tomb_bytes = if (liveness) |l| l.tomb_bits.len * @sizeOf(usize) else 0;
1919 const liveness_extra_bytes = if (liveness) |l| l.extra.len * @sizeOf(u32) else 0;
2020 const liveness_special_bytes = if (liveness) |l| l.special.count() * 8 else 0;
2121 const total_bytes = @sizeOf(Air) + instruction_bytes + extra_bytes +
22 values_bytes + @sizeOf(Liveness) + liveness_extra_bytes +
22 @sizeOf(Liveness) + liveness_extra_bytes +
2323 liveness_special_bytes + tomb_bytes;
2424
2525 // zig fmt: off
......@@ -27,7 +27,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
2727 \\# Total AIR+Liveness bytes: {}
2828 \\# AIR Instructions: {d} ({})
2929 \\# AIR Extra Data: {d} ({})
30 \\# AIR Values Bytes: {d} ({})
3130 \\# Liveness tomb_bits: {}
3231 \\# Liveness Extra Data: {d} ({})
3332 \\# Liveness special table: {d} ({})
......@@ -36,7 +35,6 @@ pub fn write(stream: anytype, module: *Module, air: Air, liveness: ?Liveness) vo
3635 fmtIntSizeBin(total_bytes),
3736 air.instructions.len, fmtIntSizeBin(instruction_bytes),
3837 air.extra.len, fmtIntSizeBin(extra_bytes),
39 air.values.len, fmtIntSizeBin(values_bytes),
4038 fmtIntSizeBin(tomb_bytes),
4139 if (liveness) |l| l.extra.len else 0, fmtIntSizeBin(liveness_extra_bytes),
4240 if (liveness) |l| l.special.count() else 0, fmtIntSizeBin(liveness_special_bytes),
......@@ -92,14 +90,10 @@ const Writer = struct {
9290
9391 fn writeAllConstants(w: *Writer, s: anytype) @TypeOf(s).Error!void {
9492 for (w.air.instructions.items(.tag), 0..) |tag, i| {
93 if (tag != .interned) continue;
9594 const inst = @intCast(Air.Inst.Index, i);
96 switch (tag) {
97 .constant, .const_ty => {
98 try w.writeInst(s, inst);
99 try s.writeByte('\n');
100 },
101 else => continue,
102 }
95 try w.writeInst(s, inst);
96 try s.writeByte('\n');
10397 }
10498 }
10599
......@@ -225,7 +219,6 @@ const Writer = struct {
225219 .save_err_return_trace_index,
226220 => try w.writeNoOp(s, inst),
227221
228 .const_ty,
229222 .alloc,
230223 .ret_ptr,
231224 .err_return_trace,
......@@ -304,7 +297,9 @@ const Writer = struct {
304297
305298 .struct_field_ptr => try w.writeStructField(s, inst),
306299 .struct_field_val => try w.writeStructField(s, inst),
307 .constant => try w.writeConstant(s, inst),
300 .inferred_alloc => @panic("TODO"),
301 .inferred_alloc_comptime => @panic("TODO"),
302 .interned => try w.writeInterned(s, inst),
308303 .assembly => try w.writeAssembly(s, inst),
309304 .dbg_stmt => try w.writeDbgStmt(s, inst),
310305
......@@ -364,13 +359,7 @@ const Writer = struct {
364359 }
365360
366361 fn writeType(w: *Writer, s: anytype, ty: Type) !void {
367 const t = ty.tag();
368 switch (t) {
369 .inferred_alloc_const => try s.writeAll("(inferred_alloc_const)"),
370 .inferred_alloc_mut => try s.writeAll("(inferred_alloc_mut)"),
371 .generic_poison => try s.writeAll("(generic_poison)"),
372 else => try ty.print(s, w.module),
373 }
362 return ty.print(s, w.module);
374363 }
375364
376365 fn writeTy(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
......@@ -432,9 +421,10 @@ const Writer = struct {
432421 }
433422
434423 fn writeAggregateInit(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
424 const mod = w.module;
435425 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
436426 const vector_ty = w.air.getRefType(ty_pl.ty);
437 const len = @intCast(usize, vector_ty.arrayLen());
427 const len = @intCast(usize, vector_ty.arrayLen(mod));
438428 const elements = @ptrCast([]const Air.Inst.Ref, w.air.extra[ty_pl.payload..][0..len]);
439429
440430 try w.writeType(s, vector_ty);
......@@ -511,10 +501,11 @@ const Writer = struct {
511501 }
512502
513503 fn writeSelect(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
504 const mod = w.module;
514505 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
515506 const extra = w.air.extraData(Air.Bin, pl_op.payload).data;
516507
517 const elem_ty = w.air.typeOfIndex(inst).childType();
508 const elem_ty = w.typeOfIndex(inst).childType(mod);
518509 try w.writeType(s, elem_ty);
519510 try s.writeAll(", ");
520511 try w.writeOperand(s, inst, 0, pl_op.operand);
......@@ -605,12 +596,12 @@ const Writer = struct {
605596 try s.print(", {d}", .{extra.field_index});
606597 }
607598
608 fn writeConstant(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
609 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
610 const val = w.air.values[ty_pl.payload];
611 const ty = w.air.getRefType(ty_pl.ty);
599 fn writeInterned(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
600 const mod = w.module;
601 const ip_index = w.air.instructions.items(.data)[inst].interned;
602 const ty = mod.intern_pool.indexToKey(ip_index).typeOf().toType();
612603 try w.writeType(s, ty);
613 try s.print(", {}", .{val.fmtValue(ty, w.module)});
604 try s.print(", {}", .{ip_index.toValue().fmtValue(ty, mod)});
614605 }
615606
616607 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
......@@ -621,7 +612,7 @@ const Writer = struct {
621612 var extra_i: usize = extra.end;
622613 var op_index: usize = 0;
623614
624 const ret_ty = w.air.typeOfIndex(inst);
615 const ret_ty = w.typeOfIndex(inst);
625616 try w.writeType(s, ret_ty);
626617
627618 if (is_volatile) {
......@@ -692,17 +683,17 @@ const Writer = struct {
692683 }
693684
694685 fn writeDbgInline(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
695 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
696 const function = w.air.values[ty_pl.payload].castTag(.function).?.data;
697 const owner_decl = w.module.declPtr(function.owner_decl);
698 try s.print("{s}", .{owner_decl.name});
686 const ty_fn = w.air.instructions.items(.data)[inst].ty_fn;
687 const func_index = ty_fn.func;
688 const owner_decl = w.module.declPtr(w.module.funcPtr(func_index).owner_decl);
689 try s.print("{}", .{owner_decl.name.fmt(&w.module.intern_pool)});
699690 }
700691
701692 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
702693 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
703694 try w.writeOperand(s, inst, 0, pl_op.operand);
704695 const name = w.air.nullTerminatedString(pl_op.payload);
705 try s.print(", {s}", .{name});
696 try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});
706697 }
707698
708699 fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
......@@ -965,14 +956,13 @@ const Writer = struct {
965956 operand: Air.Inst.Ref,
966957 dies: bool,
967958 ) @TypeOf(s).Error!void {
968 var i: usize = @enumToInt(operand);
959 const i = @enumToInt(operand);
969960
970 if (i < Air.Inst.Ref.typed_value_map.len) {
961 if (i < InternPool.static_len) {
971962 return s.print("@{}", .{operand});
972963 }
973 i -= Air.Inst.Ref.typed_value_map.len;
974964
975 return w.writeInstIndex(s, @intCast(Air.Inst.Index, i), dies);
965 return w.writeInstIndex(s, i - InternPool.static_len, dies);
976966 }
977967
978968 fn writeInstIndex(
......@@ -985,4 +975,9 @@ const Writer = struct {
985975 try s.print("%{d}", .{inst});
986976 if (dies) try s.writeByte('!');
987977 }
978
979 fn typeOfIndex(w: *Writer, inst: Air.Inst.Index) Type {
980 const mod = w.module;
981 return w.air.typeOfIndex(inst, &mod.intern_pool);
982 }
988983};
src/print_zir.zig+5-9
......@@ -3,6 +3,7 @@ const mem = std.mem;
33const Allocator = std.mem.Allocator;
44const assert = std.debug.assert;
55const Ast = std.zig.Ast;
6const InternPool = @import("InternPool.zig");
67
78const Zir = @import("Zir.zig");
89const Module = @import("Module.zig");
......@@ -1191,7 +1192,7 @@ const Writer = struct {
11911192 .field => {
11921193 const field_name = self.code.nullTerminatedString(extra.data.field_name_start);
11931194 try self.writeInstRef(stream, extra.data.obj_ptr);
1194 try stream.print(", {}", .{std.zig.fmtId(field_name)});
1195 try stream.print(", \"{}\"", .{std.zig.fmtEscapes(field_name)});
11951196 },
11961197 }
11971198 try stream.writeAll(", [");
......@@ -2468,14 +2469,9 @@ const Writer = struct {
24682469 }
24692470
24702471 fn writeInstRef(self: *Writer, stream: anytype, ref: Zir.Inst.Ref) !void {
2471 var i: usize = @enumToInt(ref);
2472
2473 if (i < Zir.Inst.Ref.typed_value_map.len) {
2474 return stream.print("@{}", .{ref});
2475 }
2476 i -= Zir.Inst.Ref.typed_value_map.len;
2477
2478 return self.writeInstIndex(stream, @intCast(Zir.Inst.Index, i));
2472 const i = @enumToInt(ref);
2473 if (i < InternPool.static_len) return stream.print("@{}", .{@intToEnum(InternPool.Index, i)});
2474 return self.writeInstIndex(stream, i - InternPool.static_len);
24792475 }
24802476
24812477 fn writeInstIndex(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
src/target.zig+11-128
......@@ -512,134 +512,6 @@ pub fn needUnwindTables(target: std.Target) bool {
512512 return target.os.tag == .windows;
513513}
514514
515pub const AtomicPtrAlignmentError = error{
516 FloatTooBig,
517 IntTooBig,
518 BadType,
519};
520
521pub const AtomicPtrAlignmentDiagnostics = struct {
522 bits: u16 = undefined,
523 max_bits: u16 = undefined,
524};
525
526/// If ABI alignment of `ty` is OK for atomic operations, returns 0.
527/// Otherwise returns the alignment required on a pointer for the target
528/// to perform atomic operations.
529// TODO this function does not take into account CPU features, which can affect
530// this value. Audit this!
531pub fn atomicPtrAlignment(
532 target: std.Target,
533 ty: Type,
534 diags: *AtomicPtrAlignmentDiagnostics,
535) AtomicPtrAlignmentError!u32 {
536 const max_atomic_bits: u16 = switch (target.cpu.arch) {
537 .avr,
538 .msp430,
539 .spu_2,
540 => 16,
541
542 .arc,
543 .arm,
544 .armeb,
545 .hexagon,
546 .m68k,
547 .le32,
548 .mips,
549 .mipsel,
550 .nvptx,
551 .powerpc,
552 .powerpcle,
553 .r600,
554 .riscv32,
555 .sparc,
556 .sparcel,
557 .tce,
558 .tcele,
559 .thumb,
560 .thumbeb,
561 .x86,
562 .xcore,
563 .amdil,
564 .hsail,
565 .spir,
566 .kalimba,
567 .lanai,
568 .shave,
569 .wasm32,
570 .renderscript32,
571 .csky,
572 .spirv32,
573 .dxil,
574 .loongarch32,
575 .xtensa,
576 => 32,
577
578 .amdgcn,
579 .bpfel,
580 .bpfeb,
581 .le64,
582 .mips64,
583 .mips64el,
584 .nvptx64,
585 .powerpc64,
586 .powerpc64le,
587 .riscv64,
588 .sparc64,
589 .s390x,
590 .amdil64,
591 .hsail64,
592 .spir64,
593 .wasm64,
594 .renderscript64,
595 .ve,
596 .spirv64,
597 .loongarch64,
598 => 64,
599
600 .aarch64,
601 .aarch64_be,
602 .aarch64_32,
603 => 128,
604
605 .x86_64 => if (std.Target.x86.featureSetHas(target.cpu.features, .cx16)) 128 else 64,
606 };
607
608 var buffer: Type.Payload.Bits = undefined;
609
610 const int_ty = switch (ty.zigTypeTag()) {
611 .Int => ty,
612 .Enum => ty.intTagType(&buffer),
613 .Float => {
614 const bit_count = ty.floatBits(target);
615 if (bit_count > max_atomic_bits) {
616 diags.* = .{
617 .bits = bit_count,
618 .max_bits = max_atomic_bits,
619 };
620 return error.FloatTooBig;
621 }
622 return 0;
623 },
624 .Bool => return 0,
625 else => {
626 if (ty.isPtrAtRuntime()) return 0;
627 return error.BadType;
628 },
629 };
630
631 const bit_count = int_ty.intInfo(target).bits;
632 if (bit_count > max_atomic_bits) {
633 diags.* = .{
634 .bits = bit_count,
635 .max_bits = max_atomic_bits,
636 };
637 return error.IntTooBig;
638 }
639
640 return 0;
641}
642
643515pub fn defaultAddressSpace(
644516 target: std.Target,
645517 context: enum {
......@@ -777,3 +649,14 @@ pub fn compilerRtIntAbbrev(bits: u16) []const u8 {
777649 else => "o", // Non-standard
778650 };
779651}
652
653pub fn fnCallConvAllowsZigTypes(target: std.Target, cc: std.builtin.CallingConvention) bool {
654 return switch (cc) {
655 .Unspecified, .Async, .Inline => true,
656 // For now we want to authorize PTX kernel to use zig objects, even if
657 // we end up exposing the ABI. The goal is to experiment with more
658 // integrated CPU/GPU code.
659 .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64,
660 else => false,
661 };
662}
src/type.zig+2420-5687
......@@ -9,176 +9,42 @@ const log = std.log.scoped(.Type);
99const target_util = @import("target.zig");
1010const TypedValue = @import("TypedValue.zig");
1111const Sema = @import("Sema.zig");
12const InternPool = @import("InternPool.zig");
1213
13const file_struct = @This();
14
15/// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.
16/// It's important for this type to be small.
17/// Types are not de-duplicated, which helps with multi-threading since it obviates the requirement
18/// of obtaining a lock on a global type table, as well as making the
19/// garbage collection bookkeeping simpler.
20/// This union takes advantage of the fact that the first page of memory
21/// is unmapped, giving us 4096 possible enum tags that have no payload.
22pub const Type = extern union {
23 /// If the tag value is less than Tag.no_payload_count, then no pointer
24 /// dereference is needed.
25 tag_if_small_enough: Tag,
26 ptr_otherwise: *Payload,
27
28 pub fn zigTypeTag(ty: Type) std.builtin.TypeId {
29 return ty.zigTypeTagOrPoison() catch unreachable;
30 }
31
32 pub fn zigTypeTagOrPoison(ty: Type) error{GenericPoison}!std.builtin.TypeId {
33 switch (ty.tag()) {
34 .generic_poison => return error.GenericPoison,
35
36 .u1,
37 .u8,
38 .i8,
39 .u16,
40 .i16,
41 .u29,
42 .u32,
43 .i32,
44 .u64,
45 .i64,
46 .u128,
47 .i128,
48 .usize,
49 .isize,
50 .c_char,
51 .c_short,
52 .c_ushort,
53 .c_int,
54 .c_uint,
55 .c_long,
56 .c_ulong,
57 .c_longlong,
58 .c_ulonglong,
59 .int_signed,
60 .int_unsigned,
61 => return .Int,
62
63 .f16,
64 .f32,
65 .f64,
66 .f80,
67 .f128,
68 .c_longdouble,
69 => return .Float,
70
71 .error_set,
72 .error_set_single,
73 .anyerror,
74 .error_set_inferred,
75 .error_set_merged,
76 => return .ErrorSet,
77
78 .anyopaque, .@"opaque" => return .Opaque,
79 .bool => return .Bool,
80 .void => return .Void,
81 .type => return .Type,
82 .comptime_int => return .ComptimeInt,
83 .comptime_float => return .ComptimeFloat,
84 .noreturn => return .NoReturn,
85 .null => return .Null,
86 .undefined => return .Undefined,
87
88 .fn_noreturn_no_args => return .Fn,
89 .fn_void_no_args => return .Fn,
90 .fn_naked_noreturn_no_args => return .Fn,
91 .fn_ccc_void_no_args => return .Fn,
92 .function => return .Fn,
93
94 .array,
95 .array_u8_sentinel_0,
96 .array_u8,
97 .array_sentinel,
98 => return .Array,
99
100 .vector => return .Vector,
101
102 .single_const_pointer_to_comptime_int,
103 .const_slice_u8,
104 .const_slice_u8_sentinel_0,
105 .single_const_pointer,
106 .single_mut_pointer,
107 .many_const_pointer,
108 .many_mut_pointer,
109 .c_const_pointer,
110 .c_mut_pointer,
111 .const_slice,
112 .mut_slice,
113 .pointer,
114 .inferred_alloc_const,
115 .inferred_alloc_mut,
116 .manyptr_u8,
117 .manyptr_const_u8,
118 .manyptr_const_u8_sentinel_0,
119 => return .Pointer,
120
121 .optional,
122 .optional_single_const_pointer,
123 .optional_single_mut_pointer,
124 => return .Optional,
125 .enum_literal => return .EnumLiteral,
126
127 .anyerror_void_error_union, .error_union => return .ErrorUnion,
128
129 .anyframe_T, .@"anyframe" => return .AnyFrame,
130
131 .empty_struct,
132 .empty_struct_literal,
133 .@"struct",
134 .prefetch_options,
135 .export_options,
136 .extern_options,
137 .tuple,
138 .anon_struct,
139 => return .Struct,
140
141 .enum_full,
142 .enum_nonexhaustive,
143 .enum_simple,
144 .enum_numbered,
145 .atomic_order,
146 .atomic_rmw_op,
147 .calling_convention,
148 .address_space,
149 .float_mode,
150 .reduce_op,
151 .modifier,
152 => return .Enum,
153
154 .@"union",
155 .union_safety_tagged,
156 .union_tagged,
157 .type_info,
158 => return .Union,
159 }
14/// Both types and values are canonically represented by a single 32-bit integer
15/// which is an index into an `InternPool` data structure.
16/// This struct abstracts around this storage by providing methods only
17/// applicable to types rather than values in general.
18pub const Type = struct {
19 ip_index: InternPool.Index,
20
21 pub fn zigTypeTag(ty: Type, mod: *const Module) std.builtin.TypeId {
22 return ty.zigTypeTagOrPoison(mod) catch unreachable;
16023 }
16124
162 pub fn baseZigTypeTag(self: Type) std.builtin.TypeId {
163 return switch (self.zigTypeTag()) {
164 .ErrorUnion => self.errorUnionPayload().baseZigTypeTag(),
25 pub fn zigTypeTagOrPoison(ty: Type, mod: *const Module) error{GenericPoison}!std.builtin.TypeId {
26 return mod.intern_pool.zigTypeTagOrPoison(ty.toIntern());
27 }
28
29 pub fn baseZigTypeTag(self: Type, mod: *Module) std.builtin.TypeId {
30 return switch (self.zigTypeTag(mod)) {
31 .ErrorUnion => self.errorUnionPayload(mod).baseZigTypeTag(mod),
16532 .Optional => {
166 var buf: Payload.ElemType = undefined;
167 return self.optionalChild(&buf).baseZigTypeTag();
33 return self.optionalChild(mod).baseZigTypeTag(mod);
16834 },
16935 else => |t| t,
17036 };
17137 }
17238
173 pub fn isSelfComparable(ty: Type, is_equality_cmp: bool) bool {
174 return switch (ty.zigTypeTag()) {
39 pub fn isSelfComparable(ty: Type, mod: *const Module, is_equality_cmp: bool) bool {
40 return switch (ty.zigTypeTag(mod)) {
17541 .Int,
17642 .Float,
17743 .ComptimeFloat,
17844 .ComptimeInt,
17945 => true,
18046
181 .Vector => ty.elemType2().isSelfComparable(is_equality_cmp),
47 .Vector => ty.elemType2(mod).isSelfComparable(mod, is_equality_cmp),
18248
18349 .Bool,
18450 .Type,
......@@ -201,1317 +67,70 @@ pub const Type = extern union {
20167 .Frame,
20268 => false,
20369
204 .Pointer => !ty.isSlice() and (is_equality_cmp or ty.isCPtr()),
70 .Pointer => !ty.isSlice(mod) and (is_equality_cmp or ty.isCPtr(mod)),
20571 .Optional => {
20672 if (!is_equality_cmp) return false;
207 var buf: Payload.ElemType = undefined;
208 return ty.optionalChild(&buf).isSelfComparable(is_equality_cmp);
73 return ty.optionalChild(mod).isSelfComparable(mod, is_equality_cmp);
20974 },
21075 };
21176 }
21277
213 pub fn initTag(comptime small_tag: Tag) Type {
214 comptime assert(@enumToInt(small_tag) < Tag.no_payload_count);
215 return .{ .tag_if_small_enough = small_tag };
216 }
217
218 pub fn initPayload(payload: *Payload) Type {
219 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
220 return .{ .ptr_otherwise = payload };
221 }
222
223 pub fn tag(self: Type) Tag {
224 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
225 return self.tag_if_small_enough;
226 } else {
227 return self.ptr_otherwise.tag;
228 }
229 }
230
231 /// Prefer `castTag` to this.
232 pub fn cast(self: Type, comptime T: type) ?*T {
233 if (@hasField(T, "base_tag")) {
234 return self.castTag(T.base_tag);
235 }
236 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
237 return null;
238 }
239 inline for (@typeInfo(Tag).Enum.fields) |field| {
240 if (field.value < Tag.no_payload_count)
241 continue;
242 const t = @intToEnum(Tag, field.value);
243 if (self.ptr_otherwise.tag == t) {
244 if (T == t.Type()) {
245 return @fieldParentPtr(T, "base", self.ptr_otherwise);
246 }
247 return null;
248 }
249 }
250 unreachable;
251 }
252
253 pub fn castTag(self: Type, comptime t: Tag) ?*t.Type() {
254 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count)
255 return null;
256
257 if (self.ptr_otherwise.tag == t)
258 return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise);
259
260 return null;
261 }
262
263 pub fn castPointer(self: Type) ?*Payload.ElemType {
264 return switch (self.tag()) {
265 .single_const_pointer,
266 .single_mut_pointer,
267 .many_const_pointer,
268 .many_mut_pointer,
269 .c_const_pointer,
270 .c_mut_pointer,
271 .const_slice,
272 .mut_slice,
273 .optional_single_const_pointer,
274 .optional_single_mut_pointer,
275 .manyptr_u8,
276 .manyptr_const_u8,
277 .manyptr_const_u8_sentinel_0,
278 => self.cast(Payload.ElemType),
279
280 .inferred_alloc_const => unreachable,
281 .inferred_alloc_mut => unreachable,
282
283 else => null,
284 };
285 }
286
28778 /// If it is a function pointer, returns the function type. Otherwise returns null.
288 pub fn castPtrToFn(ty: Type) ?Type {
289 if (ty.zigTypeTag() != .Pointer) return null;
290 const elem_ty = ty.childType();
291 if (elem_ty.zigTypeTag() != .Fn) return null;
79 pub fn castPtrToFn(ty: Type, mod: *const Module) ?Type {
80 if (ty.zigTypeTag(mod) != .Pointer) return null;
81 const elem_ty = ty.childType(mod);
82 if (elem_ty.zigTypeTag(mod) != .Fn) return null;
29283 return elem_ty;
29384 }
29485
295 pub fn ptrIsMutable(ty: Type) bool {
296 return switch (ty.tag()) {
297 .single_const_pointer_to_comptime_int,
298 .const_slice_u8,
299 .const_slice_u8_sentinel_0,
300 .single_const_pointer,
301 .many_const_pointer,
302 .manyptr_const_u8,
303 .manyptr_const_u8_sentinel_0,
304 .c_const_pointer,
305 .const_slice,
306 => false,
307
308 .single_mut_pointer,
309 .many_mut_pointer,
310 .manyptr_u8,
311 .c_mut_pointer,
312 .mut_slice,
313 => true,
314
315 .pointer => ty.castTag(.pointer).?.data.mutable,
316
317 else => unreachable,
318 };
319 }
320
321 pub const ArrayInfo = struct { elem_type: Type, sentinel: ?Value = null, len: u64 };
322 pub fn arrayInfo(self: Type) ArrayInfo {
323 return .{
324 .len = self.arrayLen(),
325 .sentinel = self.sentinel(),
326 .elem_type = self.elemType(),
327 };
86 /// Asserts the type is a pointer.
87 pub fn ptrIsMutable(ty: Type, mod: *const Module) bool {
88 return !mod.intern_pool.indexToKey(ty.toIntern()).ptr_type.flags.is_const;
32889 }
32990
330 pub fn ptrInfo(self: Type) Payload.Pointer {
331 switch (self.tag()) {
332 .single_const_pointer_to_comptime_int => return .{ .data = .{
333 .pointee_type = Type.initTag(.comptime_int),
334 .sentinel = null,
335 .@"align" = 0,
336 .@"addrspace" = .generic,
337 .bit_offset = 0,
338 .host_size = 0,
339 .@"allowzero" = false,
340 .mutable = false,
341 .@"volatile" = false,
342 .size = .One,
343 } },
344 .const_slice_u8 => return .{ .data = .{
345 .pointee_type = Type.initTag(.u8),
346 .sentinel = null,
347 .@"align" = 0,
348 .@"addrspace" = .generic,
349 .bit_offset = 0,
350 .host_size = 0,
351 .@"allowzero" = false,
352 .mutable = false,
353 .@"volatile" = false,
354 .size = .Slice,
355 } },
356 .const_slice_u8_sentinel_0 => return .{ .data = .{
357 .pointee_type = Type.initTag(.u8),
358 .sentinel = Value.zero,
359 .@"align" = 0,
360 .@"addrspace" = .generic,
361 .bit_offset = 0,
362 .host_size = 0,
363 .@"allowzero" = false,
364 .mutable = false,
365 .@"volatile" = false,
366 .size = .Slice,
367 } },
368 .single_const_pointer => return .{ .data = .{
369 .pointee_type = self.castPointer().?.data,
370 .sentinel = null,
371 .@"align" = 0,
372 .@"addrspace" = .generic,
373 .bit_offset = 0,
374 .host_size = 0,
375 .@"allowzero" = false,
376 .mutable = false,
377 .@"volatile" = false,
378 .size = .One,
379 } },
380 .single_mut_pointer => return .{ .data = .{
381 .pointee_type = self.castPointer().?.data,
382 .sentinel = null,
383 .@"align" = 0,
384 .@"addrspace" = .generic,
385 .bit_offset = 0,
386 .host_size = 0,
387 .@"allowzero" = false,
388 .mutable = true,
389 .@"volatile" = false,
390 .size = .One,
391 } },
392 .many_const_pointer => return .{ .data = .{
393 .pointee_type = self.castPointer().?.data,
394 .sentinel = null,
395 .@"align" = 0,
396 .@"addrspace" = .generic,
397 .bit_offset = 0,
398 .host_size = 0,
399 .@"allowzero" = false,
400 .mutable = false,
401 .@"volatile" = false,
402 .size = .Many,
403 } },
404 .manyptr_const_u8 => return .{ .data = .{
405 .pointee_type = Type.initTag(.u8),
406 .sentinel = null,
407 .@"align" = 0,
408 .@"addrspace" = .generic,
409 .bit_offset = 0,
410 .host_size = 0,
411 .@"allowzero" = false,
412 .mutable = false,
413 .@"volatile" = false,
414 .size = .Many,
415 } },
416 .manyptr_const_u8_sentinel_0 => return .{ .data = .{
417 .pointee_type = Type.initTag(.u8),
418 .sentinel = Value.zero,
419 .@"align" = 0,
420 .@"addrspace" = .generic,
421 .bit_offset = 0,
422 .host_size = 0,
423 .@"allowzero" = false,
424 .mutable = false,
425 .@"volatile" = false,
426 .size = .Many,
427 } },
428 .many_mut_pointer => return .{ .data = .{
429 .pointee_type = self.castPointer().?.data,
430 .sentinel = null,
431 .@"align" = 0,
432 .@"addrspace" = .generic,
433 .bit_offset = 0,
434 .host_size = 0,
435 .@"allowzero" = false,
436 .mutable = true,
437 .@"volatile" = false,
438 .size = .Many,
439 } },
440 .manyptr_u8 => return .{ .data = .{
441 .pointee_type = Type.initTag(.u8),
442 .sentinel = null,
443 .@"align" = 0,
444 .@"addrspace" = .generic,
445 .bit_offset = 0,
446 .host_size = 0,
447 .@"allowzero" = false,
448 .mutable = true,
449 .@"volatile" = false,
450 .size = .Many,
451 } },
452 .c_const_pointer => return .{ .data = .{
453 .pointee_type = self.castPointer().?.data,
454 .sentinel = null,
455 .@"align" = 0,
456 .@"addrspace" = .generic,
457 .bit_offset = 0,
458 .host_size = 0,
459 .@"allowzero" = true,
460 .mutable = false,
461 .@"volatile" = false,
462 .size = .C,
463 } },
464 .c_mut_pointer => return .{ .data = .{
465 .pointee_type = self.castPointer().?.data,
466 .sentinel = null,
467 .@"align" = 0,
468 .@"addrspace" = .generic,
469 .bit_offset = 0,
470 .host_size = 0,
471 .@"allowzero" = true,
472 .mutable = true,
473 .@"volatile" = false,
474 .size = .C,
475 } },
476 .const_slice => return .{ .data = .{
477 .pointee_type = self.castPointer().?.data,
478 .sentinel = null,
479 .@"align" = 0,
480 .@"addrspace" = .generic,
481 .bit_offset = 0,
482 .host_size = 0,
483 .@"allowzero" = false,
484 .mutable = false,
485 .@"volatile" = false,
486 .size = .Slice,
487 } },
488 .mut_slice => return .{ .data = .{
489 .pointee_type = self.castPointer().?.data,
490 .sentinel = null,
491 .@"align" = 0,
492 .@"addrspace" = .generic,
493 .bit_offset = 0,
494 .host_size = 0,
495 .@"allowzero" = false,
496 .mutable = true,
497 .@"volatile" = false,
498 .size = .Slice,
499 } },
500
501 .pointer => return self.castTag(.pointer).?.*,
502
503 .optional_single_mut_pointer => return .{ .data = .{
504 .pointee_type = self.castPointer().?.data,
505 .sentinel = null,
506 .@"align" = 0,
507 .@"addrspace" = .generic,
508 .bit_offset = 0,
509 .host_size = 0,
510 .@"allowzero" = false,
511 .mutable = true,
512 .@"volatile" = false,
513 .size = .One,
514 } },
515 .optional_single_const_pointer => return .{ .data = .{
516 .pointee_type = self.castPointer().?.data,
517 .sentinel = null,
518 .@"align" = 0,
519 .@"addrspace" = .generic,
520 .bit_offset = 0,
521 .host_size = 0,
522 .@"allowzero" = false,
523 .mutable = false,
524 .@"volatile" = false,
525 .size = .One,
526 } },
527 .optional => {
528 var buf: Payload.ElemType = undefined;
529 const child_type = self.optionalChild(&buf);
530 return child_type.ptrInfo();
531 },
532
533 else => unreachable,
534 }
535 }
536
537 pub fn eql(a: Type, b: Type, mod: *Module) bool {
538 // As a shortcut, if the small tags / addresses match, we're done.
539 if (a.tag_if_small_enough == b.tag_if_small_enough) return true;
540
541 switch (a.tag()) {
542 .generic_poison => unreachable,
543
544 // Detect that e.g. u64 != usize, even if the bits match on a particular target.
545 .usize,
546 .isize,
547 .c_char,
548 .c_short,
549 .c_ushort,
550 .c_int,
551 .c_uint,
552 .c_long,
553 .c_ulong,
554 .c_longlong,
555 .c_ulonglong,
556
557 .f16,
558 .f32,
559 .f64,
560 .f80,
561 .f128,
562 .c_longdouble,
563
564 .bool,
565 .void,
566 .type,
567 .comptime_int,
568 .comptime_float,
569 .noreturn,
570 .null,
571 .undefined,
572 .anyopaque,
573 .@"anyframe",
574 .enum_literal,
575 => |a_tag| {
576 assert(a_tag != b.tag()); // because of the comparison at the top of the function.
577 return false;
578 },
579
580 .u1,
581 .u8,
582 .i8,
583 .u16,
584 .i16,
585 .u29,
586 .u32,
587 .i32,
588 .u64,
589 .i64,
590 .u128,
591 .i128,
592 .int_signed,
593 .int_unsigned,
594 => {
595 if (b.zigTypeTag() != .Int) return false;
596 if (b.isNamedInt()) return false;
597
598 // Arbitrary sized integers. The target will not be branched upon,
599 // because we handled target-dependent cases above.
600 const info_a = a.intInfo(@as(Target, undefined));
601 const info_b = b.intInfo(@as(Target, undefined));
602 return info_a.signedness == info_b.signedness and info_a.bits == info_b.bits;
603 },
604
605 .error_set_inferred => {
606 // Inferred error sets are only equal if both are inferred
607 // and they share the same pointer.
608 const a_ies = a.castTag(.error_set_inferred).?.data;
609 const b_ies = (b.castTag(.error_set_inferred) orelse return false).data;
610 return a_ies == b_ies;
611 },
612
613 .anyerror => {
614 return b.tag() == .anyerror;
615 },
616
617 .error_set,
618 .error_set_single,
619 .error_set_merged,
620 => {
621 switch (b.tag()) {
622 .error_set, .error_set_single, .error_set_merged => {},
623 else => return false,
624 }
625
626 // Two resolved sets match if their error set names match.
627 // Since they are pre-sorted we compare them element-wise.
628 const a_set = a.errorSetNames();
629 const b_set = b.errorSetNames();
630 if (a_set.len != b_set.len) return false;
631 for (a_set, 0..) |a_item, i| {
632 const b_item = b_set[i];
633 if (!std.mem.eql(u8, a_item, b_item)) return false;
634 }
635 return true;
636 },
637
638 .@"opaque" => {
639 const opaque_obj_a = a.castTag(.@"opaque").?.data;
640 const opaque_obj_b = (b.castTag(.@"opaque") orelse return false).data;
641 return opaque_obj_a == opaque_obj_b;
642 },
643
644 .fn_noreturn_no_args,
645 .fn_void_no_args,
646 .fn_naked_noreturn_no_args,
647 .fn_ccc_void_no_args,
648 .function,
649 => {
650 if (b.zigTypeTag() != .Fn) return false;
651
652 const a_info = a.fnInfo();
653 const b_info = b.fnInfo();
654
655 if (a_info.return_type.tag() != .generic_poison and
656 b_info.return_type.tag() != .generic_poison and
657 !eql(a_info.return_type, b_info.return_type, mod))
658 return false;
659
660 if (a_info.is_var_args != b_info.is_var_args)
661 return false;
662
663 if (a_info.is_generic != b_info.is_generic)
664 return false;
665
666 if (a_info.is_noinline != b_info.is_noinline)
667 return false;
668
669 if (a_info.noalias_bits != b_info.noalias_bits)
670 return false;
671
672 if (!a_info.cc_is_generic and a_info.cc != b_info.cc)
673 return false;
674
675 if (!a_info.align_is_generic and a_info.alignment != b_info.alignment)
676 return false;
677
678 if (a_info.param_types.len != b_info.param_types.len)
679 return false;
680
681 for (a_info.param_types, 0..) |a_param_ty, i| {
682 const b_param_ty = b_info.param_types[i];
683 if (a_info.comptime_params[i] != b_info.comptime_params[i])
684 return false;
685
686 if (a_param_ty.tag() == .generic_poison) continue;
687 if (b_param_ty.tag() == .generic_poison) continue;
688
689 if (!eql(a_param_ty, b_param_ty, mod))
690 return false;
691 }
692
693 return true;
694 },
695
696 .array,
697 .array_u8_sentinel_0,
698 .array_u8,
699 .array_sentinel,
700 .vector,
701 => {
702 if (a.zigTypeTag() != b.zigTypeTag()) return false;
703
704 if (a.arrayLen() != b.arrayLen())
705 return false;
706 const elem_ty = a.elemType();
707 if (!elem_ty.eql(b.elemType(), mod))
708 return false;
709 const sentinel_a = a.sentinel();
710 const sentinel_b = b.sentinel();
711 if (sentinel_a) |sa| {
712 if (sentinel_b) |sb| {
713 return sa.eql(sb, elem_ty, mod);
714 } else {
715 return false;
716 }
717 } else {
718 return sentinel_b == null;
719 }
720 },
721
722 .single_const_pointer_to_comptime_int,
723 .const_slice_u8,
724 .const_slice_u8_sentinel_0,
725 .single_const_pointer,
726 .single_mut_pointer,
727 .many_const_pointer,
728 .many_mut_pointer,
729 .c_const_pointer,
730 .c_mut_pointer,
731 .const_slice,
732 .mut_slice,
733 .pointer,
734 .inferred_alloc_const,
735 .inferred_alloc_mut,
736 .manyptr_u8,
737 .manyptr_const_u8,
738 .manyptr_const_u8_sentinel_0,
739 => {
740 if (b.zigTypeTag() != .Pointer) return false;
741
742 const info_a = a.ptrInfo().data;
743 const info_b = b.ptrInfo().data;
744 if (!info_a.pointee_type.eql(info_b.pointee_type, mod))
745 return false;
746 if (info_a.@"align" != info_b.@"align")
747 return false;
748 if (info_a.@"addrspace" != info_b.@"addrspace")
749 return false;
750 if (info_a.bit_offset != info_b.bit_offset)
751 return false;
752 if (info_a.host_size != info_b.host_size)
753 return false;
754 if (info_a.vector_index != info_b.vector_index)
755 return false;
756 if (info_a.@"allowzero" != info_b.@"allowzero")
757 return false;
758 if (info_a.mutable != info_b.mutable)
759 return false;
760 if (info_a.@"volatile" != info_b.@"volatile")
761 return false;
762 if (info_a.size != info_b.size)
763 return false;
764
765 const sentinel_a = info_a.sentinel;
766 const sentinel_b = info_b.sentinel;
767 if (sentinel_a) |sa| {
768 if (sentinel_b) |sb| {
769 if (!sa.eql(sb, info_a.pointee_type, mod))
770 return false;
771 } else {
772 return false;
773 }
774 } else {
775 if (sentinel_b != null)
776 return false;
777 }
778
779 return true;
780 },
781
782 .optional,
783 .optional_single_const_pointer,
784 .optional_single_mut_pointer,
785 => {
786 if (b.zigTypeTag() != .Optional) return false;
787
788 var buf_a: Payload.ElemType = undefined;
789 var buf_b: Payload.ElemType = undefined;
790 return a.optionalChild(&buf_a).eql(b.optionalChild(&buf_b), mod);
791 },
792
793 .anyerror_void_error_union, .error_union => {
794 if (b.zigTypeTag() != .ErrorUnion) return false;
795
796 const a_set = a.errorUnionSet();
797 const b_set = b.errorUnionSet();
798 if (!a_set.eql(b_set, mod)) return false;
799
800 const a_payload = a.errorUnionPayload();
801 const b_payload = b.errorUnionPayload();
802 if (!a_payload.eql(b_payload, mod)) return false;
803
804 return true;
805 },
806
807 .anyframe_T => {
808 if (b.zigTypeTag() != .AnyFrame) return false;
809 return a.elemType2().eql(b.elemType2(), mod);
810 },
811
812 .empty_struct => {
813 const a_namespace = a.castTag(.empty_struct).?.data;
814 const b_namespace = (b.castTag(.empty_struct) orelse return false).data;
815 return a_namespace == b_namespace;
816 },
817 .@"struct" => {
818 const a_struct_obj = a.castTag(.@"struct").?.data;
819 const b_struct_obj = (b.castTag(.@"struct") orelse return false).data;
820 return a_struct_obj == b_struct_obj;
821 },
822 .tuple, .empty_struct_literal => {
823 if (!b.isSimpleTuple()) return false;
824
825 const a_tuple = a.tupleFields();
826 const b_tuple = b.tupleFields();
827
828 if (a_tuple.types.len != b_tuple.types.len) return false;
829
830 for (a_tuple.types, 0..) |a_ty, i| {
831 const b_ty = b_tuple.types[i];
832 if (!eql(a_ty, b_ty, mod)) return false;
833 }
834
835 for (a_tuple.values, 0..) |a_val, i| {
836 const ty = a_tuple.types[i];
837 const b_val = b_tuple.values[i];
838 if (a_val.tag() == .unreachable_value) {
839 if (b_val.tag() == .unreachable_value) {
840 continue;
841 } else {
842 return false;
843 }
844 } else {
845 if (b_val.tag() == .unreachable_value) {
846 return false;
847 } else {
848 if (!Value.eql(a_val, b_val, ty, mod)) return false;
849 }
850 }
851 }
852
853 return true;
854 },
855 .anon_struct => {
856 const a_struct_obj = a.castTag(.anon_struct).?.data;
857 const b_struct_obj = (b.castTag(.anon_struct) orelse return false).data;
858
859 if (a_struct_obj.types.len != b_struct_obj.types.len) return false;
860
861 for (a_struct_obj.names, 0..) |a_name, i| {
862 const b_name = b_struct_obj.names[i];
863 if (!std.mem.eql(u8, a_name, b_name)) return false;
864 }
865
866 for (a_struct_obj.types, 0..) |a_ty, i| {
867 const b_ty = b_struct_obj.types[i];
868 if (!eql(a_ty, b_ty, mod)) return false;
869 }
870
871 for (a_struct_obj.values, 0..) |a_val, i| {
872 const ty = a_struct_obj.types[i];
873 const b_val = b_struct_obj.values[i];
874 if (a_val.tag() == .unreachable_value) {
875 if (b_val.tag() == .unreachable_value) {
876 continue;
877 } else {
878 return false;
879 }
880 } else {
881 if (b_val.tag() == .unreachable_value) {
882 return false;
883 } else {
884 if (!Value.eql(a_val, b_val, ty, mod)) return false;
885 }
886 }
887 }
888
889 return true;
890 },
891
892 // we can't compare these based on tags because it wouldn't detect if,
893 // for example, a was resolved into .@"struct" but b was one of these tags.
894 .prefetch_options,
895 .export_options,
896 .extern_options,
897 => unreachable, // needed to resolve the type before now
898
899 .enum_full, .enum_nonexhaustive => {
900 const a_enum_obj = a.cast(Payload.EnumFull).?.data;
901 const b_enum_obj = (b.cast(Payload.EnumFull) orelse return false).data;
902 return a_enum_obj == b_enum_obj;
903 },
904 .enum_simple => {
905 const a_enum_obj = a.cast(Payload.EnumSimple).?.data;
906 const b_enum_obj = (b.cast(Payload.EnumSimple) orelse return false).data;
907 return a_enum_obj == b_enum_obj;
908 },
909 .enum_numbered => {
910 const a_enum_obj = a.cast(Payload.EnumNumbered).?.data;
911 const b_enum_obj = (b.cast(Payload.EnumNumbered) orelse return false).data;
912 return a_enum_obj == b_enum_obj;
913 },
914 // we can't compare these based on tags because it wouldn't detect if,
915 // for example, a was resolved into .enum_simple but b was one of these tags.
916 .atomic_order,
917 .atomic_rmw_op,
918 .calling_convention,
919 .address_space,
920 .float_mode,
921 .reduce_op,
922 .modifier,
923 => unreachable, // needed to resolve the type before now
924
925 .@"union", .union_safety_tagged, .union_tagged => {
926 const a_union_obj = a.cast(Payload.Union).?.data;
927 const b_union_obj = (b.cast(Payload.Union) orelse return false).data;
928 return a_union_obj == b_union_obj;
929 },
930 // we can't compare these based on tags because it wouldn't detect if,
931 // for example, a was resolved into .union_tagged but b was one of these tags.
932 .type_info => unreachable, // needed to resolve the type before now
933
934 }
935 }
936
937 pub fn hash(self: Type, mod: *Module) u64 {
938 var hasher = std.hash.Wyhash.init(0);
939 self.hashWithHasher(&hasher, mod);
940 return hasher.final();
941 }
942
943 pub fn hashWithHasher(ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
944 switch (ty.tag()) {
945 .generic_poison => unreachable,
946
947 .usize,
948 .isize,
949 .c_char,
950 .c_short,
951 .c_ushort,
952 .c_int,
953 .c_uint,
954 .c_long,
955 .c_ulong,
956 .c_longlong,
957 .c_ulonglong,
958 => |ty_tag| {
959 std.hash.autoHash(hasher, std.builtin.TypeId.Int);
960 std.hash.autoHash(hasher, ty_tag);
961 },
962
963 .f16,
964 .f32,
965 .f64,
966 .f80,
967 .f128,
968 .c_longdouble,
969 => |ty_tag| {
970 std.hash.autoHash(hasher, std.builtin.TypeId.Float);
971 std.hash.autoHash(hasher, ty_tag);
972 },
973
974 .bool => std.hash.autoHash(hasher, std.builtin.TypeId.Bool),
975 .void => std.hash.autoHash(hasher, std.builtin.TypeId.Void),
976 .type => std.hash.autoHash(hasher, std.builtin.TypeId.Type),
977 .comptime_int => std.hash.autoHash(hasher, std.builtin.TypeId.ComptimeInt),
978 .comptime_float => std.hash.autoHash(hasher, std.builtin.TypeId.ComptimeFloat),
979 .noreturn => std.hash.autoHash(hasher, std.builtin.TypeId.NoReturn),
980 .null => std.hash.autoHash(hasher, std.builtin.TypeId.Null),
981 .undefined => std.hash.autoHash(hasher, std.builtin.TypeId.Undefined),
982
983 .anyopaque => {
984 std.hash.autoHash(hasher, std.builtin.TypeId.Opaque);
985 std.hash.autoHash(hasher, Tag.anyopaque);
986 },
987
988 .@"anyframe" => {
989 std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame);
990 std.hash.autoHash(hasher, Tag.@"anyframe");
991 },
992
993 .enum_literal => {
994 std.hash.autoHash(hasher, std.builtin.TypeId.EnumLiteral);
995 std.hash.autoHash(hasher, Tag.enum_literal);
996 },
997
998 .u1,
999 .u8,
1000 .i8,
1001 .u16,
1002 .i16,
1003 .u29,
1004 .u32,
1005 .i32,
1006 .u64,
1007 .i64,
1008 .u128,
1009 .i128,
1010 .int_signed,
1011 .int_unsigned,
1012 => {
1013 // Arbitrary sized integers. The target will not be branched upon,
1014 // because we handled target-dependent cases above.
1015 std.hash.autoHash(hasher, std.builtin.TypeId.Int);
1016 const info = ty.intInfo(@as(Target, undefined));
1017 std.hash.autoHash(hasher, info.signedness);
1018 std.hash.autoHash(hasher, info.bits);
1019 },
1020
1021 .error_set,
1022 .error_set_single,
1023 .error_set_merged,
1024 => {
1025 // all are treated like an "error set" for hashing
1026 std.hash.autoHash(hasher, std.builtin.TypeId.ErrorSet);
1027 std.hash.autoHash(hasher, Tag.error_set);
1028
1029 const names = ty.errorSetNames();
1030 std.hash.autoHash(hasher, names.len);
1031 assert(std.sort.isSorted([]const u8, names, u8, std.mem.lessThan));
1032 for (names) |name| hasher.update(name);
1033 },
1034
1035 .anyerror => {
1036 // anyerror is distinct from other error sets
1037 std.hash.autoHash(hasher, std.builtin.TypeId.ErrorSet);
1038 std.hash.autoHash(hasher, Tag.anyerror);
1039 },
1040
1041 .error_set_inferred => {
1042 // inferred error sets are compared using their data pointer
1043 const ies: *Module.Fn.InferredErrorSet = ty.castTag(.error_set_inferred).?.data;
1044 std.hash.autoHash(hasher, std.builtin.TypeId.ErrorSet);
1045 std.hash.autoHash(hasher, Tag.error_set_inferred);
1046 std.hash.autoHash(hasher, ies);
1047 },
1048
1049 .@"opaque" => {
1050 std.hash.autoHash(hasher, std.builtin.TypeId.Opaque);
1051 const opaque_obj = ty.castTag(.@"opaque").?.data;
1052 std.hash.autoHash(hasher, opaque_obj);
1053 },
1054
1055 .fn_noreturn_no_args,
1056 .fn_void_no_args,
1057 .fn_naked_noreturn_no_args,
1058 .fn_ccc_void_no_args,
1059 .function,
1060 => {
1061 std.hash.autoHash(hasher, std.builtin.TypeId.Fn);
1062
1063 const fn_info = ty.fnInfo();
1064 if (fn_info.return_type.tag() != .generic_poison) {
1065 hashWithHasher(fn_info.return_type, hasher, mod);
1066 }
1067 if (!fn_info.align_is_generic) {
1068 std.hash.autoHash(hasher, fn_info.alignment);
1069 }
1070 if (!fn_info.cc_is_generic) {
1071 std.hash.autoHash(hasher, fn_info.cc);
1072 }
1073 std.hash.autoHash(hasher, fn_info.is_var_args);
1074 std.hash.autoHash(hasher, fn_info.is_generic);
1075 std.hash.autoHash(hasher, fn_info.is_noinline);
1076 std.hash.autoHash(hasher, fn_info.noalias_bits);
1077
1078 std.hash.autoHash(hasher, fn_info.param_types.len);
1079 for (fn_info.param_types, 0..) |param_ty, i| {
1080 std.hash.autoHash(hasher, fn_info.paramIsComptime(i));
1081 if (param_ty.tag() == .generic_poison) continue;
1082 hashWithHasher(param_ty, hasher, mod);
1083 }
1084 },
1085
1086 .array,
1087 .array_u8_sentinel_0,
1088 .array_u8,
1089 .array_sentinel,
1090 => {
1091 std.hash.autoHash(hasher, std.builtin.TypeId.Array);
1092
1093 const elem_ty = ty.elemType();
1094 std.hash.autoHash(hasher, ty.arrayLen());
1095 hashWithHasher(elem_ty, hasher, mod);
1096 hashSentinel(ty.sentinel(), elem_ty, hasher, mod);
1097 },
1098
1099 .vector => {
1100 std.hash.autoHash(hasher, std.builtin.TypeId.Vector);
1101
1102 const elem_ty = ty.elemType();
1103 std.hash.autoHash(hasher, ty.vectorLen());
1104 hashWithHasher(elem_ty, hasher, mod);
1105 },
1106
1107 .single_const_pointer_to_comptime_int,
1108 .const_slice_u8,
1109 .const_slice_u8_sentinel_0,
1110 .single_const_pointer,
1111 .single_mut_pointer,
1112 .many_const_pointer,
1113 .many_mut_pointer,
1114 .c_const_pointer,
1115 .c_mut_pointer,
1116 .const_slice,
1117 .mut_slice,
1118 .pointer,
1119 .inferred_alloc_const,
1120 .inferred_alloc_mut,
1121 .manyptr_u8,
1122 .manyptr_const_u8,
1123 .manyptr_const_u8_sentinel_0,
1124 => {
1125 std.hash.autoHash(hasher, std.builtin.TypeId.Pointer);
1126
1127 const info = ty.ptrInfo().data;
1128 hashWithHasher(info.pointee_type, hasher, mod);
1129 hashSentinel(info.sentinel, info.pointee_type, hasher, mod);
1130 std.hash.autoHash(hasher, info.@"align");
1131 std.hash.autoHash(hasher, info.@"addrspace");
1132 std.hash.autoHash(hasher, info.bit_offset);
1133 std.hash.autoHash(hasher, info.host_size);
1134 std.hash.autoHash(hasher, info.vector_index);
1135 std.hash.autoHash(hasher, info.@"allowzero");
1136 std.hash.autoHash(hasher, info.mutable);
1137 std.hash.autoHash(hasher, info.@"volatile");
1138 std.hash.autoHash(hasher, info.size);
1139 },
1140
1141 .optional,
1142 .optional_single_const_pointer,
1143 .optional_single_mut_pointer,
1144 => {
1145 std.hash.autoHash(hasher, std.builtin.TypeId.Optional);
1146
1147 var buf: Payload.ElemType = undefined;
1148 hashWithHasher(ty.optionalChild(&buf), hasher, mod);
1149 },
1150
1151 .anyerror_void_error_union, .error_union => {
1152 std.hash.autoHash(hasher, std.builtin.TypeId.ErrorUnion);
1153
1154 const set_ty = ty.errorUnionSet();
1155 hashWithHasher(set_ty, hasher, mod);
1156
1157 const payload_ty = ty.errorUnionPayload();
1158 hashWithHasher(payload_ty, hasher, mod);
1159 },
1160
1161 .anyframe_T => {
1162 std.hash.autoHash(hasher, std.builtin.TypeId.AnyFrame);
1163 hashWithHasher(ty.childType(), hasher, mod);
1164 },
1165
1166 .empty_struct => {
1167 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
1168 const namespace: *const Module.Namespace = ty.castTag(.empty_struct).?.data;
1169 std.hash.autoHash(hasher, namespace);
1170 },
1171 .@"struct" => {
1172 const struct_obj: *const Module.Struct = ty.castTag(.@"struct").?.data;
1173 std.hash.autoHash(hasher, struct_obj);
1174 },
1175 .tuple, .empty_struct_literal => {
1176 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
1177
1178 const tuple = ty.tupleFields();
1179 std.hash.autoHash(hasher, tuple.types.len);
1180
1181 for (tuple.types, 0..) |field_ty, i| {
1182 hashWithHasher(field_ty, hasher, mod);
1183 const field_val = tuple.values[i];
1184 if (field_val.tag() == .unreachable_value) continue;
1185 field_val.hash(field_ty, hasher, mod);
1186 }
1187 },
1188 .anon_struct => {
1189 const struct_obj = ty.castTag(.anon_struct).?.data;
1190 std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
1191 std.hash.autoHash(hasher, struct_obj.types.len);
1192
1193 for (struct_obj.types, 0..) |field_ty, i| {
1194 const field_name = struct_obj.names[i];
1195 const field_val = struct_obj.values[i];
1196 hasher.update(field_name);
1197 hashWithHasher(field_ty, hasher, mod);
1198 if (field_val.tag() == .unreachable_value) continue;
1199 field_val.hash(field_ty, hasher, mod);
1200 }
1201 },
1202
1203 // we can't hash these based on tags because they wouldn't match the expanded version.
1204 .prefetch_options,
1205 .export_options,
1206 .extern_options,
1207 => unreachable, // needed to resolve the type before now
1208
1209 .enum_full, .enum_nonexhaustive => {
1210 const enum_obj: *const Module.EnumFull = ty.cast(Payload.EnumFull).?.data;
1211 std.hash.autoHash(hasher, std.builtin.TypeId.Enum);
1212 std.hash.autoHash(hasher, enum_obj);
1213 },
1214 .enum_simple => {
1215 const enum_obj: *const Module.EnumSimple = ty.cast(Payload.EnumSimple).?.data;
1216 std.hash.autoHash(hasher, std.builtin.TypeId.Enum);
1217 std.hash.autoHash(hasher, enum_obj);
1218 },
1219 .enum_numbered => {
1220 const enum_obj: *const Module.EnumNumbered = ty.cast(Payload.EnumNumbered).?.data;
1221 std.hash.autoHash(hasher, std.builtin.TypeId.Enum);
1222 std.hash.autoHash(hasher, enum_obj);
1223 },
1224 // we can't hash these based on tags because they wouldn't match the expanded version.
1225 .atomic_order,
1226 .atomic_rmw_op,
1227 .calling_convention,
1228 .address_space,
1229 .float_mode,
1230 .reduce_op,
1231 .modifier,
1232 => unreachable, // needed to resolve the type before now
1233
1234 .@"union", .union_safety_tagged, .union_tagged => {
1235 const union_obj: *const Module.Union = ty.cast(Payload.Union).?.data;
1236 std.hash.autoHash(hasher, std.builtin.TypeId.Union);
1237 std.hash.autoHash(hasher, union_obj);
1238 },
1239 // we can't hash these based on tags because they wouldn't match the expanded version.
1240 .type_info => unreachable, // needed to resolve the type before now
1241
1242 }
1243 }
1244
1245 fn hashSentinel(opt_val: ?Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
1246 if (opt_val) |s| {
1247 std.hash.autoHash(hasher, true);
1248 s.hash(ty, hasher, mod);
1249 } else {
1250 std.hash.autoHash(hasher, false);
1251 }
1252 }
1253
1254 pub const HashContext64 = struct {
1255 mod: *Module,
1256
1257 pub fn hash(self: @This(), t: Type) u64 {
1258 return t.hash(self.mod);
1259 }
1260 pub fn eql(self: @This(), a: Type, b: Type) bool {
1261 return a.eql(b, self.mod);
1262 }
1263 };
1264
1265 pub const HashContext32 = struct {
1266 mod: *Module,
1267
1268 pub fn hash(self: @This(), t: Type) u32 {
1269 return @truncate(u32, t.hash(self.mod));
1270 }
1271 pub fn eql(self: @This(), a: Type, b: Type, b_index: usize) bool {
1272 _ = b_index;
1273 return a.eql(b, self.mod);
1274 }
91 pub const ArrayInfo = struct {
92 elem_type: Type,
93 sentinel: ?Value = null,
94 len: u64,
127595 };
1276
1277 pub fn copy(self: Type, allocator: Allocator) error{OutOfMemory}!Type {
1278 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
1279 return Type{ .tag_if_small_enough = self.tag_if_small_enough };
1280 } else switch (self.ptr_otherwise.tag) {
1281 .u1,
1282 .u8,
1283 .i8,
1284 .u16,
1285 .i16,
1286 .u29,
1287 .u32,
1288 .i32,
1289 .u64,
1290 .i64,
1291 .u128,
1292 .i128,
1293 .usize,
1294 .isize,
1295 .c_char,
1296 .c_short,
1297 .c_ushort,
1298 .c_int,
1299 .c_uint,
1300 .c_long,
1301 .c_ulong,
1302 .c_longlong,
1303 .c_ulonglong,
1304 .c_longdouble,
1305 .anyopaque,
1306 .f16,
1307 .f32,
1308 .f64,
1309 .f80,
1310 .f128,
1311 .bool,
1312 .void,
1313 .type,
1314 .anyerror,
1315 .comptime_int,
1316 .comptime_float,
1317 .noreturn,
1318 .null,
1319 .undefined,
1320 .fn_noreturn_no_args,
1321 .fn_void_no_args,
1322 .fn_naked_noreturn_no_args,
1323 .fn_ccc_void_no_args,
1324 .single_const_pointer_to_comptime_int,
1325 .const_slice_u8,
1326 .const_slice_u8_sentinel_0,
1327 .enum_literal,
1328 .anyerror_void_error_union,
1329 .inferred_alloc_const,
1330 .inferred_alloc_mut,
1331 .empty_struct_literal,
1332 .manyptr_u8,
1333 .manyptr_const_u8,
1334 .manyptr_const_u8_sentinel_0,
1335 .atomic_order,
1336 .atomic_rmw_op,
1337 .calling_convention,
1338 .address_space,
1339 .float_mode,
1340 .reduce_op,
1341 .modifier,
1342 .prefetch_options,
1343 .export_options,
1344 .extern_options,
1345 .type_info,
1346 .@"anyframe",
1347 .generic_poison,
1348 => unreachable,
1349
1350 .array_u8,
1351 .array_u8_sentinel_0,
1352 => return self.copyPayloadShallow(allocator, Payload.Len),
1353
1354 .single_const_pointer,
1355 .single_mut_pointer,
1356 .many_const_pointer,
1357 .many_mut_pointer,
1358 .c_const_pointer,
1359 .c_mut_pointer,
1360 .const_slice,
1361 .mut_slice,
1362 .optional,
1363 .optional_single_mut_pointer,
1364 .optional_single_const_pointer,
1365 .anyframe_T,
1366 => {
1367 const payload = self.cast(Payload.ElemType).?;
1368 const new_payload = try allocator.create(Payload.ElemType);
1369 new_payload.* = .{
1370 .base = .{ .tag = payload.base.tag },
1371 .data = try payload.data.copy(allocator),
1372 };
1373 return Type{ .ptr_otherwise = &new_payload.base };
1374 },
1375
1376 .int_signed,
1377 .int_unsigned,
1378 => return self.copyPayloadShallow(allocator, Payload.Bits),
1379
1380 .vector => {
1381 const payload = self.castTag(.vector).?.data;
1382 return Tag.vector.create(allocator, .{
1383 .len = payload.len,
1384 .elem_type = try payload.elem_type.copy(allocator),
1385 });
1386 },
1387 .array => {
1388 const payload = self.castTag(.array).?.data;
1389 return Tag.array.create(allocator, .{
1390 .len = payload.len,
1391 .elem_type = try payload.elem_type.copy(allocator),
1392 });
1393 },
1394 .array_sentinel => {
1395 const payload = self.castTag(.array_sentinel).?.data;
1396 return Tag.array_sentinel.create(allocator, .{
1397 .len = payload.len,
1398 .sentinel = try payload.sentinel.copy(allocator),
1399 .elem_type = try payload.elem_type.copy(allocator),
1400 });
1401 },
1402 .tuple => {
1403 const payload = self.castTag(.tuple).?.data;
1404 const types = try allocator.alloc(Type, payload.types.len);
1405 const values = try allocator.alloc(Value, payload.values.len);
1406 for (payload.types, 0..) |ty, i| {
1407 types[i] = try ty.copy(allocator);
1408 }
1409 for (payload.values, 0..) |val, i| {
1410 values[i] = try val.copy(allocator);
1411 }
1412 return Tag.tuple.create(allocator, .{
1413 .types = types,
1414 .values = values,
1415 });
1416 },
1417 .anon_struct => {
1418 const payload = self.castTag(.anon_struct).?.data;
1419 const names = try allocator.alloc([]const u8, payload.names.len);
1420 const types = try allocator.alloc(Type, payload.types.len);
1421 const values = try allocator.alloc(Value, payload.values.len);
1422 for (payload.names, 0..) |name, i| {
1423 names[i] = try allocator.dupe(u8, name);
1424 }
1425 for (payload.types, 0..) |ty, i| {
1426 types[i] = try ty.copy(allocator);
1427 }
1428 for (payload.values, 0..) |val, i| {
1429 values[i] = try val.copy(allocator);
1430 }
1431 return Tag.anon_struct.create(allocator, .{
1432 .names = names,
1433 .types = types,
1434 .values = values,
1435 });
1436 },
1437 .function => {
1438 const payload = self.castTag(.function).?.data;
1439 const param_types = try allocator.alloc(Type, payload.param_types.len);
1440 for (payload.param_types, 0..) |param_ty, i| {
1441 param_types[i] = try param_ty.copy(allocator);
1442 }
1443 const other_comptime_params = payload.comptime_params[0..payload.param_types.len];
1444 const comptime_params = try allocator.dupe(bool, other_comptime_params);
1445 return Tag.function.create(allocator, .{
1446 .return_type = try payload.return_type.copy(allocator),
1447 .param_types = param_types,
1448 .cc = payload.cc,
1449 .alignment = payload.alignment,
1450 .is_var_args = payload.is_var_args,
1451 .is_generic = payload.is_generic,
1452 .is_noinline = payload.is_noinline,
1453 .comptime_params = comptime_params.ptr,
1454 .align_is_generic = payload.align_is_generic,
1455 .cc_is_generic = payload.cc_is_generic,
1456 .section_is_generic = payload.section_is_generic,
1457 .addrspace_is_generic = payload.addrspace_is_generic,
1458 .noalias_bits = payload.noalias_bits,
1459 });
1460 },
1461 .pointer => {
1462 const payload = self.castTag(.pointer).?.data;
1463 const sent: ?Value = if (payload.sentinel) |some|
1464 try some.copy(allocator)
1465 else
1466 null;
1467 return Tag.pointer.create(allocator, .{
1468 .pointee_type = try payload.pointee_type.copy(allocator),
1469 .sentinel = sent,
1470 .@"align" = payload.@"align",
1471 .@"addrspace" = payload.@"addrspace",
1472 .bit_offset = payload.bit_offset,
1473 .host_size = payload.host_size,
1474 .vector_index = payload.vector_index,
1475 .@"allowzero" = payload.@"allowzero",
1476 .mutable = payload.mutable,
1477 .@"volatile" = payload.@"volatile",
1478 .size = payload.size,
1479 });
1480 },
1481 .error_union => {
1482 const payload = self.castTag(.error_union).?.data;
1483 return Tag.error_union.create(allocator, .{
1484 .error_set = try payload.error_set.copy(allocator),
1485 .payload = try payload.payload.copy(allocator),
1486 });
1487 },
1488 .error_set_merged => {
1489 const names = self.castTag(.error_set_merged).?.data.keys();
1490 var duped_names = Module.ErrorSet.NameMap{};
1491 try duped_names.ensureTotalCapacity(allocator, names.len);
1492 for (names) |name| {
1493 duped_names.putAssumeCapacityNoClobber(name, {});
1494 }
1495 return Tag.error_set_merged.create(allocator, duped_names);
96
97 pub fn arrayInfo(self: Type, mod: *const Module) ArrayInfo {
98 return .{
99 .len = self.arrayLen(mod),
100 .sentinel = self.sentinel(mod),
101 .elem_type = self.childType(mod),
102 };
103 }
104
105 pub fn ptrInfoIp(ip: *const InternPool, ty: InternPool.Index) InternPool.Key.PtrType {
106 return switch (ip.indexToKey(ty)) {
107 .ptr_type => |p| p,
108 .opt_type => |child| switch (ip.indexToKey(child)) {
109 .ptr_type => |p| p,
110 else => unreachable,
1496111 },
1497 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
1498 .error_set_inferred => return self.copyPayloadShallow(allocator, Payload.ErrorSetInferred),
1499 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
1500 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
1501 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
1502 .@"union", .union_safety_tagged, .union_tagged => return self.copyPayloadShallow(allocator, Payload.Union),
1503 .enum_simple => return self.copyPayloadShallow(allocator, Payload.EnumSimple),
1504 .enum_numbered => return self.copyPayloadShallow(allocator, Payload.EnumNumbered),
1505 .enum_full, .enum_nonexhaustive => return self.copyPayloadShallow(allocator, Payload.EnumFull),
1506 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
1507 }
112 else => unreachable,
113 };
1508114 }
1509115
1510 fn copyPayloadShallow(self: Type, allocator: Allocator, comptime T: type) error{OutOfMemory}!Type {
1511 const payload = self.cast(T).?;
1512 const new_payload = try allocator.create(T);
1513 new_payload.* = payload.*;
1514 return Type{ .ptr_otherwise = &new_payload.base };
116 pub fn ptrInfo(ty: Type, mod: *const Module) Payload.Pointer.Data {
117 return Payload.Pointer.Data.fromKey(ptrInfoIp(&mod.intern_pool, ty.toIntern()));
118 }
119
120 pub fn eql(a: Type, b: Type, mod: *const Module) bool {
121 _ = mod; // TODO: remove this parameter
122 // The InternPool data structure hashes based on Key to make interned objects
123 // unique. An Index can be treated simply as u32 value for the
124 // purpose of Type/Value hashing and equality.
125 return a.toIntern() == b.toIntern();
126 }
127
128 pub fn hash(ty: Type, mod: *const Module) u32 {
129 _ = mod; // TODO: remove this parameter
130 // The InternPool data structure hashes based on Key to make interned objects
131 // unique. An Index can be treated simply as u32 value for the
132 // purpose of Type/Value hashing and equality.
133 return std.hash.uint32(@enumToInt(ty.toIntern()));
1515134 }
1516135
1517136 pub fn format(ty: Type, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
......@@ -1550,7 +169,7 @@ pub const Type = extern union {
1550169 }
1551170
1552171 /// This is a debug function. In order to print types in a meaningful way
1553 /// we also need access to the target.
172 /// we also need access to the module.
1554173 pub fn dump(
1555174 start_type: Type,
1556175 comptime unused_format_string: []const u8,
......@@ -1559,372 +178,7 @@ pub const Type = extern union {
1559178 ) @TypeOf(writer).Error!void {
1560179 _ = options;
1561180 comptime assert(unused_format_string.len == 0);
1562 if (true) {
1563 // This is disabled to work around a bug where this function
1564 // recursively causes more generic function instantiations
1565 // resulting in an infinite loop in the compiler.
1566 try writer.writeAll("[TODO fix internal compiler bug regarding dump]");
1567 return;
1568 }
1569 var ty = start_type;
1570 while (true) {
1571 const t = ty.tag();
1572 switch (t) {
1573 .u1,
1574 .u8,
1575 .i8,
1576 .u16,
1577 .i16,
1578 .u29,
1579 .u32,
1580 .i32,
1581 .u64,
1582 .i64,
1583 .u128,
1584 .i128,
1585 .usize,
1586 .isize,
1587 .c_char,
1588 .c_short,
1589 .c_ushort,
1590 .c_int,
1591 .c_uint,
1592 .c_long,
1593 .c_ulong,
1594 .c_longlong,
1595 .c_ulonglong,
1596 .c_longdouble,
1597 .anyopaque,
1598 .f16,
1599 .f32,
1600 .f64,
1601 .f80,
1602 .f128,
1603 .bool,
1604 .void,
1605 .type,
1606 .anyerror,
1607 .@"anyframe",
1608 .comptime_int,
1609 .comptime_float,
1610 .noreturn,
1611 => return writer.writeAll(@tagName(t)),
1612
1613 .enum_literal => return writer.writeAll("@Type(.EnumLiteral)"),
1614 .null => return writer.writeAll("@Type(.Null)"),
1615 .undefined => return writer.writeAll("@Type(.Undefined)"),
1616
1617 .empty_struct, .empty_struct_literal => return writer.writeAll("struct {}"),
1618
1619 .@"struct" => {
1620 const struct_obj = ty.castTag(.@"struct").?.data;
1621 return writer.print("({s} decl={d})", .{
1622 @tagName(t), struct_obj.owner_decl,
1623 });
1624 },
1625 .@"union", .union_safety_tagged, .union_tagged => {
1626 const union_obj = ty.cast(Payload.Union).?.data;
1627 return writer.print("({s} decl={d})", .{
1628 @tagName(t), union_obj.owner_decl,
1629 });
1630 },
1631 .enum_full, .enum_nonexhaustive => {
1632 const enum_full = ty.cast(Payload.EnumFull).?.data;
1633 return writer.print("({s} decl={d})", .{
1634 @tagName(t), enum_full.owner_decl,
1635 });
1636 },
1637 .enum_simple => {
1638 const enum_simple = ty.castTag(.enum_simple).?.data;
1639 return writer.print("({s} decl={d})", .{
1640 @tagName(t), enum_simple.owner_decl,
1641 });
1642 },
1643 .enum_numbered => {
1644 const enum_numbered = ty.castTag(.enum_numbered).?.data;
1645 return writer.print("({s} decl={d})", .{
1646 @tagName(t), enum_numbered.owner_decl,
1647 });
1648 },
1649 .@"opaque" => {
1650 const opaque_obj = ty.castTag(.@"opaque").?.data;
1651 return writer.print("({s} decl={d})", .{
1652 @tagName(t), opaque_obj.owner_decl,
1653 });
1654 },
1655
1656 .anyerror_void_error_union => return writer.writeAll("anyerror!void"),
1657 .const_slice_u8 => return writer.writeAll("[]const u8"),
1658 .const_slice_u8_sentinel_0 => return writer.writeAll("[:0]const u8"),
1659 .fn_noreturn_no_args => return writer.writeAll("fn() noreturn"),
1660 .fn_void_no_args => return writer.writeAll("fn() void"),
1661 .fn_naked_noreturn_no_args => return writer.writeAll("fn() callconv(.Naked) noreturn"),
1662 .fn_ccc_void_no_args => return writer.writeAll("fn() callconv(.C) void"),
1663 .single_const_pointer_to_comptime_int => return writer.writeAll("*const comptime_int"),
1664 .manyptr_u8 => return writer.writeAll("[*]u8"),
1665 .manyptr_const_u8 => return writer.writeAll("[*]const u8"),
1666 .manyptr_const_u8_sentinel_0 => return writer.writeAll("[*:0]const u8"),
1667 .atomic_order => return writer.writeAll("std.builtin.AtomicOrder"),
1668 .atomic_rmw_op => return writer.writeAll("std.builtin.AtomicRmwOp"),
1669 .calling_convention => return writer.writeAll("std.builtin.CallingConvention"),
1670 .address_space => return writer.writeAll("std.builtin.AddressSpace"),
1671 .float_mode => return writer.writeAll("std.builtin.FloatMode"),
1672 .reduce_op => return writer.writeAll("std.builtin.ReduceOp"),
1673 .modifier => return writer.writeAll("std.builtin.CallModifier"),
1674 .prefetch_options => return writer.writeAll("std.builtin.PrefetchOptions"),
1675 .export_options => return writer.writeAll("std.builtin.ExportOptions"),
1676 .extern_options => return writer.writeAll("std.builtin.ExternOptions"),
1677 .type_info => return writer.writeAll("std.builtin.Type"),
1678 .function => {
1679 const payload = ty.castTag(.function).?.data;
1680 try writer.writeAll("fn(");
1681 for (payload.param_types, 0..) |param_type, i| {
1682 if (i != 0) try writer.writeAll(", ");
1683 try param_type.dump("", .{}, writer);
1684 }
1685 if (payload.is_var_args) {
1686 if (payload.param_types.len != 0) {
1687 try writer.writeAll(", ");
1688 }
1689 try writer.writeAll("...");
1690 }
1691 try writer.writeAll(") ");
1692 if (payload.alignment != 0) {
1693 try writer.print("align({d}) ", .{payload.alignment});
1694 }
1695 if (payload.cc != .Unspecified) {
1696 try writer.writeAll("callconv(.");
1697 try writer.writeAll(@tagName(payload.cc));
1698 try writer.writeAll(") ");
1699 }
1700 ty = payload.return_type;
1701 continue;
1702 },
1703
1704 .anyframe_T => {
1705 const return_type = ty.castTag(.anyframe_T).?.data;
1706 try writer.print("anyframe->", .{});
1707 ty = return_type;
1708 continue;
1709 },
1710 .array_u8 => {
1711 const len = ty.castTag(.array_u8).?.data;
1712 return writer.print("[{d}]u8", .{len});
1713 },
1714 .array_u8_sentinel_0 => {
1715 const len = ty.castTag(.array_u8_sentinel_0).?.data;
1716 return writer.print("[{d}:0]u8", .{len});
1717 },
1718 .vector => {
1719 const payload = ty.castTag(.vector).?.data;
1720 try writer.print("@Vector({d}, ", .{payload.len});
1721 try payload.elem_type.dump("", .{}, writer);
1722 return writer.writeAll(")");
1723 },
1724 .array => {
1725 const payload = ty.castTag(.array).?.data;
1726 try writer.print("[{d}]", .{payload.len});
1727 ty = payload.elem_type;
1728 continue;
1729 },
1730 .array_sentinel => {
1731 const payload = ty.castTag(.array_sentinel).?.data;
1732 try writer.print("[{d}:{}]", .{
1733 payload.len,
1734 payload.sentinel.fmtDebug(),
1735 });
1736 ty = payload.elem_type;
1737 continue;
1738 },
1739 .tuple => {
1740 const tuple = ty.castTag(.tuple).?.data;
1741 try writer.writeAll("tuple{");
1742 for (tuple.types, 0..) |field_ty, i| {
1743 if (i != 0) try writer.writeAll(", ");
1744 const val = tuple.values[i];
1745 if (val.tag() != .unreachable_value) {
1746 try writer.writeAll("comptime ");
1747 }
1748 try field_ty.dump("", .{}, writer);
1749 if (val.tag() != .unreachable_value) {
1750 try writer.print(" = {}", .{val.fmtDebug()});
1751 }
1752 }
1753 try writer.writeAll("}");
1754 return;
1755 },
1756 .anon_struct => {
1757 const anon_struct = ty.castTag(.anon_struct).?.data;
1758 try writer.writeAll("struct{");
1759 for (anon_struct.types, 0..) |field_ty, i| {
1760 if (i != 0) try writer.writeAll(", ");
1761 const val = anon_struct.values[i];
1762 if (val.tag() != .unreachable_value) {
1763 try writer.writeAll("comptime ");
1764 }
1765 try writer.writeAll(anon_struct.names[i]);
1766 try writer.writeAll(": ");
1767 try field_ty.dump("", .{}, writer);
1768 if (val.tag() != .unreachable_value) {
1769 try writer.print(" = {}", .{val.fmtDebug()});
1770 }
1771 }
1772 try writer.writeAll("}");
1773 return;
1774 },
1775 .single_const_pointer => {
1776 const pointee_type = ty.castTag(.single_const_pointer).?.data;
1777 try writer.writeAll("*const ");
1778 ty = pointee_type;
1779 continue;
1780 },
1781 .single_mut_pointer => {
1782 const pointee_type = ty.castTag(.single_mut_pointer).?.data;
1783 try writer.writeAll("*");
1784 ty = pointee_type;
1785 continue;
1786 },
1787 .many_const_pointer => {
1788 const pointee_type = ty.castTag(.many_const_pointer).?.data;
1789 try writer.writeAll("[*]const ");
1790 ty = pointee_type;
1791 continue;
1792 },
1793 .many_mut_pointer => {
1794 const pointee_type = ty.castTag(.many_mut_pointer).?.data;
1795 try writer.writeAll("[*]");
1796 ty = pointee_type;
1797 continue;
1798 },
1799 .c_const_pointer => {
1800 const pointee_type = ty.castTag(.c_const_pointer).?.data;
1801 try writer.writeAll("[*c]const ");
1802 ty = pointee_type;
1803 continue;
1804 },
1805 .c_mut_pointer => {
1806 const pointee_type = ty.castTag(.c_mut_pointer).?.data;
1807 try writer.writeAll("[*c]");
1808 ty = pointee_type;
1809 continue;
1810 },
1811 .const_slice => {
1812 const pointee_type = ty.castTag(.const_slice).?.data;
1813 try writer.writeAll("[]const ");
1814 ty = pointee_type;
1815 continue;
1816 },
1817 .mut_slice => {
1818 const pointee_type = ty.castTag(.mut_slice).?.data;
1819 try writer.writeAll("[]");
1820 ty = pointee_type;
1821 continue;
1822 },
1823 .int_signed => {
1824 const bits = ty.castTag(.int_signed).?.data;
1825 return writer.print("i{d}", .{bits});
1826 },
1827 .int_unsigned => {
1828 const bits = ty.castTag(.int_unsigned).?.data;
1829 return writer.print("u{d}", .{bits});
1830 },
1831 .optional => {
1832 const child_type = ty.castTag(.optional).?.data;
1833 try writer.writeByte('?');
1834 ty = child_type;
1835 continue;
1836 },
1837 .optional_single_const_pointer => {
1838 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;
1839 try writer.writeAll("?*const ");
1840 ty = pointee_type;
1841 continue;
1842 },
1843 .optional_single_mut_pointer => {
1844 const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data;
1845 try writer.writeAll("?*");
1846 ty = pointee_type;
1847 continue;
1848 },
1849
1850 .pointer => {
1851 const payload = ty.castTag(.pointer).?.data;
1852 if (payload.sentinel) |some| switch (payload.size) {
1853 .One, .C => unreachable,
1854 .Many => try writer.print("[*:{}]", .{some.fmtDebug()}),
1855 .Slice => try writer.print("[:{}]", .{some.fmtDebug()}),
1856 } else switch (payload.size) {
1857 .One => try writer.writeAll("*"),
1858 .Many => try writer.writeAll("[*]"),
1859 .C => try writer.writeAll("[*c]"),
1860 .Slice => try writer.writeAll("[]"),
1861 }
1862 if (payload.@"align" != 0 or payload.host_size != 0 or payload.vector_index != .none) {
1863 try writer.print("align({d}", .{payload.@"align"});
1864
1865 if (payload.bit_offset != 0 or payload.host_size != 0) {
1866 try writer.print(":{d}:{d}", .{ payload.bit_offset, payload.host_size });
1867 }
1868 if (payload.vector_index == .runtime) {
1869 try writer.writeAll(":?");
1870 } else if (payload.vector_index != .none) {
1871 try writer.print(":{d}", .{@enumToInt(payload.vector_index)});
1872 }
1873 try writer.writeAll(") ");
1874 }
1875 if (payload.@"addrspace" != .generic) {
1876 try writer.print("addrspace(.{s}) ", .{@tagName(payload.@"addrspace")});
1877 }
1878 if (!payload.mutable) try writer.writeAll("const ");
1879 if (payload.@"volatile") try writer.writeAll("volatile ");
1880 if (payload.@"allowzero" and payload.size != .C) try writer.writeAll("allowzero ");
1881
1882 ty = payload.pointee_type;
1883 continue;
1884 },
1885 .error_union => {
1886 const payload = ty.castTag(.error_union).?.data;
1887 try payload.error_set.dump("", .{}, writer);
1888 try writer.writeAll("!");
1889 ty = payload.payload;
1890 continue;
1891 },
1892 .error_set => {
1893 const names = ty.castTag(.error_set).?.data.names.keys();
1894 try writer.writeAll("error{");
1895 for (names, 0..) |name, i| {
1896 if (i != 0) try writer.writeByte(',');
1897 try writer.writeAll(name);
1898 }
1899 try writer.writeAll("}");
1900 return;
1901 },
1902 .error_set_inferred => {
1903 const func = ty.castTag(.error_set_inferred).?.data.func;
1904 return writer.print("({s} func={d})", .{
1905 @tagName(t), func.owner_decl,
1906 });
1907 },
1908 .error_set_merged => {
1909 const names = ty.castTag(.error_set_merged).?.data.keys();
1910 try writer.writeAll("error{");
1911 for (names, 0..) |name, i| {
1912 if (i != 0) try writer.writeByte(',');
1913 try writer.writeAll(name);
1914 }
1915 try writer.writeAll("}");
1916 return;
1917 },
1918 .error_set_single => {
1919 const name = ty.castTag(.error_set_single).?.data;
1920 return writer.print("error{{{s}}}", .{name});
1921 },
1922 .inferred_alloc_const => return writer.writeAll("(inferred_alloc_const)"),
1923 .inferred_alloc_mut => return writer.writeAll("(inferred_alloc_mut)"),
1924 .generic_poison => return writer.writeAll("(generic poison)"),
1925 }
1926 unreachable;
1927 }
181 return writer.print("{any}", .{start_type.ip_index});
1928182 }
1929183
1930184 pub const nameAllocArena = nameAlloc;
......@@ -1938,253 +192,16 @@ pub const Type = extern union {
1938192
1939193 /// Prints a name suitable for `@typeName`.
1940194 pub fn print(ty: Type, writer: anytype, mod: *Module) @TypeOf(writer).Error!void {
1941 const t = ty.tag();
1942 switch (t) {
1943 .inferred_alloc_const => unreachable,
1944 .inferred_alloc_mut => unreachable,
1945 .generic_poison => unreachable,
1946
1947 // TODO get rid of these Type.Tag values.
1948 .atomic_order => unreachable,
1949 .atomic_rmw_op => unreachable,
1950 .calling_convention => unreachable,
1951 .address_space => unreachable,
1952 .float_mode => unreachable,
1953 .reduce_op => unreachable,
1954 .modifier => unreachable,
1955 .prefetch_options => unreachable,
1956 .export_options => unreachable,
1957 .extern_options => unreachable,
1958 .type_info => unreachable,
1959
1960 .u1,
1961 .u8,
1962 .i8,
1963 .u16,
1964 .i16,
1965 .u29,
1966 .u32,
1967 .i32,
1968 .u64,
1969 .i64,
1970 .u128,
1971 .i128,
1972 .usize,
1973 .isize,
1974 .c_char,
1975 .c_short,
1976 .c_ushort,
1977 .c_int,
1978 .c_uint,
1979 .c_long,
1980 .c_ulong,
1981 .c_longlong,
1982 .c_ulonglong,
1983 .c_longdouble,
1984 .anyopaque,
1985 .f16,
1986 .f32,
1987 .f64,
1988 .f80,
1989 .f128,
1990 .bool,
1991 .void,
1992 .type,
1993 .anyerror,
1994 .@"anyframe",
1995 .comptime_int,
1996 .comptime_float,
1997 .noreturn,
1998 => try writer.writeAll(@tagName(t)),
1999
2000 .enum_literal => try writer.writeAll("@TypeOf(.enum_literal)"),
2001 .null => try writer.writeAll("@TypeOf(null)"),
2002 .undefined => try writer.writeAll("@TypeOf(undefined)"),
2003 .empty_struct_literal => try writer.writeAll("@TypeOf(.{})"),
2004
2005 .empty_struct => {
2006 const namespace = ty.castTag(.empty_struct).?.data;
2007 try namespace.renderFullyQualifiedName(mod, "", writer);
2008 },
2009
2010 .@"struct" => {
2011 const struct_obj = ty.castTag(.@"struct").?.data;
2012 const decl = mod.declPtr(struct_obj.owner_decl);
2013 try decl.renderFullyQualifiedName(mod, writer);
2014 },
2015 .@"union", .union_safety_tagged, .union_tagged => {
2016 const union_obj = ty.cast(Payload.Union).?.data;
2017 const decl = mod.declPtr(union_obj.owner_decl);
2018 try decl.renderFullyQualifiedName(mod, writer);
2019 },
2020 .enum_full, .enum_nonexhaustive => {
2021 const enum_full = ty.cast(Payload.EnumFull).?.data;
2022 const decl = mod.declPtr(enum_full.owner_decl);
2023 try decl.renderFullyQualifiedName(mod, writer);
2024 },
2025 .enum_simple => {
2026 const enum_simple = ty.castTag(.enum_simple).?.data;
2027 const decl = mod.declPtr(enum_simple.owner_decl);
2028 try decl.renderFullyQualifiedName(mod, writer);
2029 },
2030 .enum_numbered => {
2031 const enum_numbered = ty.castTag(.enum_numbered).?.data;
2032 const decl = mod.declPtr(enum_numbered.owner_decl);
2033 try decl.renderFullyQualifiedName(mod, writer);
2034 },
2035 .@"opaque" => {
2036 const opaque_obj = ty.cast(Payload.Opaque).?.data;
2037 const decl = mod.declPtr(opaque_obj.owner_decl);
2038 try decl.renderFullyQualifiedName(mod, writer);
2039 },
2040
2041 .anyerror_void_error_union => try writer.writeAll("anyerror!void"),
2042 .const_slice_u8 => try writer.writeAll("[]const u8"),
2043 .const_slice_u8_sentinel_0 => try writer.writeAll("[:0]const u8"),
2044 .fn_noreturn_no_args => try writer.writeAll("fn() noreturn"),
2045 .fn_void_no_args => try writer.writeAll("fn() void"),
2046 .fn_naked_noreturn_no_args => try writer.writeAll("fn() callconv(.Naked) noreturn"),
2047 .fn_ccc_void_no_args => try writer.writeAll("fn() callconv(.C) void"),
2048 .single_const_pointer_to_comptime_int => try writer.writeAll("*const comptime_int"),
2049 .manyptr_u8 => try writer.writeAll("[*]u8"),
2050 .manyptr_const_u8 => try writer.writeAll("[*]const u8"),
2051 .manyptr_const_u8_sentinel_0 => try writer.writeAll("[*:0]const u8"),
2052
2053 .error_set_inferred => {
2054 const func = ty.castTag(.error_set_inferred).?.data.func;
2055
2056 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
2057 const owner_decl = mod.declPtr(func.owner_decl);
2058 try owner_decl.renderFullyQualifiedName(mod, writer);
2059 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
2060 },
2061
2062 .function => {
2063 const fn_info = ty.fnInfo();
2064 if (fn_info.is_noinline) {
2065 try writer.writeAll("noinline ");
2066 }
2067 try writer.writeAll("fn(");
2068 for (fn_info.param_types, 0..) |param_ty, i| {
2069 if (i != 0) try writer.writeAll(", ");
2070 if (fn_info.paramIsComptime(i)) {
2071 try writer.writeAll("comptime ");
2072 }
2073 if (std.math.cast(u5, i)) |index| if (@truncate(u1, fn_info.noalias_bits >> index) != 0) {
2074 try writer.writeAll("noalias ");
2075 };
2076 if (param_ty.tag() == .generic_poison) {
2077 try writer.writeAll("anytype");
2078 } else {
2079 try print(param_ty, writer, mod);
2080 }
2081 }
2082 if (fn_info.is_var_args) {
2083 if (fn_info.param_types.len != 0) {
2084 try writer.writeAll(", ");
2085 }
2086 try writer.writeAll("...");
2087 }
2088 try writer.writeAll(") ");
2089 if (fn_info.alignment != 0) {
2090 try writer.print("align({d}) ", .{fn_info.alignment});
2091 }
2092 if (fn_info.cc != .Unspecified) {
2093 try writer.writeAll("callconv(.");
2094 try writer.writeAll(@tagName(fn_info.cc));
2095 try writer.writeAll(") ");
2096 }
2097 if (fn_info.return_type.tag() == .generic_poison) {
2098 try writer.writeAll("anytype");
2099 } else {
2100 try print(fn_info.return_type, writer, mod);
2101 }
2102 },
2103
2104 .error_union => {
2105 const error_union = ty.castTag(.error_union).?.data;
2106 try print(error_union.error_set, writer, mod);
2107 try writer.writeAll("!");
2108 try print(error_union.payload, writer, mod);
2109 },
2110
2111 .array_u8 => {
2112 const len = ty.castTag(.array_u8).?.data;
2113 try writer.print("[{d}]u8", .{len});
2114 },
2115 .array_u8_sentinel_0 => {
2116 const len = ty.castTag(.array_u8_sentinel_0).?.data;
2117 try writer.print("[{d}:0]u8", .{len});
2118 },
2119 .vector => {
2120 const payload = ty.castTag(.vector).?.data;
2121 try writer.print("@Vector({d}, ", .{payload.len});
2122 try print(payload.elem_type, writer, mod);
2123 try writer.writeAll(")");
2124 },
2125 .array => {
2126 const payload = ty.castTag(.array).?.data;
2127 try writer.print("[{d}]", .{payload.len});
2128 try print(payload.elem_type, writer, mod);
2129 },
2130 .array_sentinel => {
2131 const payload = ty.castTag(.array_sentinel).?.data;
2132 try writer.print("[{d}:{}]", .{
2133 payload.len,
2134 payload.sentinel.fmtValue(payload.elem_type, mod),
2135 });
2136 try print(payload.elem_type, writer, mod);
2137 },
2138 .tuple => {
2139 const tuple = ty.castTag(.tuple).?.data;
2140
2141 try writer.writeAll("tuple{");
2142 for (tuple.types, 0..) |field_ty, i| {
2143 if (i != 0) try writer.writeAll(", ");
2144 const val = tuple.values[i];
2145 if (val.tag() != .unreachable_value) {
2146 try writer.writeAll("comptime ");
2147 }
2148 try print(field_ty, writer, mod);
2149 if (val.tag() != .unreachable_value) {
2150 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
2151 }
2152 }
2153 try writer.writeAll("}");
2154 },
2155 .anon_struct => {
2156 const anon_struct = ty.castTag(.anon_struct).?.data;
2157
2158 try writer.writeAll("struct{");
2159 for (anon_struct.types, 0..) |field_ty, i| {
2160 if (i != 0) try writer.writeAll(", ");
2161 const val = anon_struct.values[i];
2162 if (val.tag() != .unreachable_value) {
2163 try writer.writeAll("comptime ");
2164 }
2165 try writer.writeAll(anon_struct.names[i]);
2166 try writer.writeAll(": ");
2167
2168 try print(field_ty, writer, mod);
2169
2170 if (val.tag() != .unreachable_value) {
2171 try writer.print(" = {}", .{val.fmtValue(field_ty, mod)});
2172 }
2173 }
2174 try writer.writeAll("}");
195 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
196 .int_type => |int_type| {
197 const sign_char: u8 = switch (int_type.signedness) {
198 .signed => 'i',
199 .unsigned => 'u',
200 };
201 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
2175202 },
2176
2177 .pointer,
2178 .single_const_pointer,
2179 .single_mut_pointer,
2180 .many_const_pointer,
2181 .many_mut_pointer,
2182 .c_const_pointer,
2183 .c_mut_pointer,
2184 .const_slice,
2185 .mut_slice,
2186 => {
2187 const info = ty.ptrInfo().data;
203 .ptr_type => {
204 const info = ty.ptrInfo(mod);
2188205
2189206 if (info.sentinel) |s| switch (info.size) {
2190207 .One, .C => unreachable,
......@@ -2200,7 +217,7 @@ pub const Type = extern union {
2200217 if (info.@"align" != 0) {
2201218 try writer.print("align({d}", .{info.@"align"});
2202219 } else {
2203 const alignment = info.pointee_type.abiAlignment(mod.getTarget());
220 const alignment = info.pointee_type.abiAlignment(mod);
2204221 try writer.print("align({d}", .{alignment});
2205222 }
2206223
......@@ -2222,127 +239,228 @@ pub const Type = extern union {
2222239 if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
2223240
2224241 try print(info.pointee_type, writer, mod);
242 return;
243 },
244 .array_type => |array_type| {
245 if (array_type.sentinel == .none) {
246 try writer.print("[{d}]", .{array_type.len});
247 try print(array_type.child.toType(), writer, mod);
248 } else {
249 try writer.print("[{d}:{}]", .{
250 array_type.len,
251 array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod),
252 });
253 try print(array_type.child.toType(), writer, mod);
254 }
255 return;
256 },
257 .vector_type => |vector_type| {
258 try writer.print("@Vector({d}, ", .{vector_type.len});
259 try print(vector_type.child.toType(), writer, mod);
260 try writer.writeAll(")");
261 return;
262 },
263 .opt_type => |child| {
264 try writer.writeByte('?');
265 return print(child.toType(), writer, mod);
266 },
267 .error_union_type => |error_union_type| {
268 try print(error_union_type.error_set_type.toType(), writer, mod);
269 try writer.writeByte('!');
270 try print(error_union_type.payload_type.toType(), writer, mod);
271 return;
272 },
273 .inferred_error_set_type => |index| {
274 const ies = mod.inferredErrorSetPtr(index);
275 const func = ies.func;
276
277 try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
278 const owner_decl = mod.declPtr(mod.funcPtr(func).owner_decl);
279 try owner_decl.renderFullyQualifiedName(mod, writer);
280 try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
281 },
282 .error_set_type => |error_set_type| {
283 const names = error_set_type.names;
284 try writer.writeAll("error{");
285 for (names, 0..) |name, i| {
286 if (i != 0) try writer.writeByte(',');
287 try writer.print("{}", .{name.fmt(&mod.intern_pool)});
288 }
289 try writer.writeAll("}");
290 },
291 .simple_type => |s| switch (s) {
292 .f16,
293 .f32,
294 .f64,
295 .f80,
296 .f128,
297 .usize,
298 .isize,
299 .c_char,
300 .c_short,
301 .c_ushort,
302 .c_int,
303 .c_uint,
304 .c_long,
305 .c_ulong,
306 .c_longlong,
307 .c_ulonglong,
308 .c_longdouble,
309 .anyopaque,
310 .bool,
311 .void,
312 .type,
313 .anyerror,
314 .comptime_int,
315 .comptime_float,
316 .noreturn,
317 => return writer.writeAll(@tagName(s)),
318
319 .null,
320 .undefined,
321 => try writer.print("@TypeOf({s})", .{@tagName(s)}),
322
323 .enum_literal => try writer.print("@TypeOf(.{s})", .{@tagName(s)}),
324 .atomic_order => try writer.writeAll("std.builtin.AtomicOrder"),
325 .atomic_rmw_op => try writer.writeAll("std.builtin.AtomicRmwOp"),
326 .calling_convention => try writer.writeAll("std.builtin.CallingConvention"),
327 .address_space => try writer.writeAll("std.builtin.AddressSpace"),
328 .float_mode => try writer.writeAll("std.builtin.FloatMode"),
329 .reduce_op => try writer.writeAll("std.builtin.ReduceOp"),
330 .call_modifier => try writer.writeAll("std.builtin.CallModifier"),
331 .prefetch_options => try writer.writeAll("std.builtin.PrefetchOptions"),
332 .export_options => try writer.writeAll("std.builtin.ExportOptions"),
333 .extern_options => try writer.writeAll("std.builtin.ExternOptions"),
334 .type_info => try writer.writeAll("std.builtin.Type"),
335
336 .generic_poison => unreachable,
337 },
338 .struct_type => |struct_type| {
339 if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
340 const decl = mod.declPtr(struct_obj.owner_decl);
341 try decl.renderFullyQualifiedName(mod, writer);
342 } else if (struct_type.namespace.unwrap()) |namespace_index| {
343 const namespace = mod.namespacePtr(namespace_index);
344 try namespace.renderFullyQualifiedName(mod, .empty, writer);
345 } else {
346 try writer.writeAll("@TypeOf(.{})");
347 }
348 },
349 .anon_struct_type => |anon_struct| {
350 if (anon_struct.types.len == 0) {
351 return writer.writeAll("@TypeOf(.{})");
352 }
353 try writer.writeAll("struct{");
354 for (anon_struct.types, anon_struct.values, 0..) |field_ty, val, i| {
355 if (i != 0) try writer.writeAll(", ");
356 if (val != .none) {
357 try writer.writeAll("comptime ");
358 }
359 if (anon_struct.names.len != 0) {
360 try writer.print("{}: ", .{anon_struct.names[i].fmt(&mod.intern_pool)});
361 }
362
363 try print(field_ty.toType(), writer, mod);
364
365 if (val != .none) {
366 try writer.print(" = {}", .{val.toValue().fmtValue(field_ty.toType(), mod)});
367 }
368 }
369 try writer.writeAll("}");
2225370 },
2226371
2227 .int_signed => {
2228 const bits = ty.castTag(.int_signed).?.data;
2229 return writer.print("i{d}", .{bits});
2230 },
2231 .int_unsigned => {
2232 const bits = ty.castTag(.int_unsigned).?.data;
2233 return writer.print("u{d}", .{bits});
2234 },
2235 .optional => {
2236 const child_type = ty.castTag(.optional).?.data;
2237 try writer.writeByte('?');
2238 try print(child_type, writer, mod);
2239 },
2240 .optional_single_mut_pointer => {
2241 const pointee_type = ty.castTag(.optional_single_mut_pointer).?.data;
2242 try writer.writeAll("?*");
2243 try print(pointee_type, writer, mod);
372 .union_type => |union_type| {
373 const union_obj = mod.unionPtr(union_type.index);
374 const decl = mod.declPtr(union_obj.owner_decl);
375 try decl.renderFullyQualifiedName(mod, writer);
2244376 },
2245 .optional_single_const_pointer => {
2246 const pointee_type = ty.castTag(.optional_single_const_pointer).?.data;
2247 try writer.writeAll("?*const ");
2248 try print(pointee_type, writer, mod);
377 .opaque_type => |opaque_type| {
378 const decl = mod.declPtr(opaque_type.decl);
379 try decl.renderFullyQualifiedName(mod, writer);
2249380 },
2250 .anyframe_T => {
2251 const return_type = ty.castTag(.anyframe_T).?.data;
2252 try writer.print("anyframe->", .{});
2253 try print(return_type, writer, mod);
381 .enum_type => |enum_type| {
382 const decl = mod.declPtr(enum_type.decl);
383 try decl.renderFullyQualifiedName(mod, writer);
2254384 },
2255 .error_set => {
2256 const names = ty.castTag(.error_set).?.data.names.keys();
2257 try writer.writeAll("error{");
2258 for (names, 0..) |name, i| {
2259 if (i != 0) try writer.writeByte(',');
2260 try writer.writeAll(name);
385 .func_type => |fn_info| {
386 if (fn_info.is_noinline) {
387 try writer.writeAll("noinline ");
2261388 }
2262 try writer.writeAll("}");
2263 },
2264 .error_set_single => {
2265 const name = ty.castTag(.error_set_single).?.data;
2266 return writer.print("error{{{s}}}", .{name});
2267 },
2268 .error_set_merged => {
2269 const names = ty.castTag(.error_set_merged).?.data.keys();
2270 try writer.writeAll("error{");
2271 for (names, 0..) |name, i| {
2272 if (i != 0) try writer.writeByte(',');
2273 try writer.writeAll(name);
389 try writer.writeAll("fn(");
390 for (fn_info.param_types, 0..) |param_ty, i| {
391 if (i != 0) try writer.writeAll(", ");
392 if (std.math.cast(u5, i)) |index| {
393 if (fn_info.paramIsComptime(index)) {
394 try writer.writeAll("comptime ");
395 }
396 if (fn_info.paramIsNoalias(index)) {
397 try writer.writeAll("noalias ");
398 }
399 }
400 if (param_ty == .generic_poison_type) {
401 try writer.writeAll("anytype");
402 } else {
403 try print(param_ty.toType(), writer, mod);
404 }
2274405 }
2275 try writer.writeAll("}");
406 if (fn_info.is_var_args) {
407 if (fn_info.param_types.len != 0) {
408 try writer.writeAll(", ");
409 }
410 try writer.writeAll("...");
411 }
412 try writer.writeAll(") ");
413 if (fn_info.alignment.toByteUnitsOptional()) |a| {
414 try writer.print("align({d}) ", .{a});
415 }
416 if (fn_info.cc != .Unspecified) {
417 try writer.writeAll("callconv(.");
418 try writer.writeAll(@tagName(fn_info.cc));
419 try writer.writeAll(") ");
420 }
421 if (fn_info.return_type == .generic_poison_type) {
422 try writer.writeAll("anytype");
423 } else {
424 try print(fn_info.return_type.toType(), writer, mod);
425 }
426 },
427 .anyframe_type => |child| {
428 if (child == .none) return writer.writeAll("anyframe");
429 try writer.writeAll("anyframe->");
430 return print(child.toType(), writer, mod);
2276431 },
432
433 // values, not types
434 .undef,
435 .runtime_value,
436 .simple_value,
437 .variable,
438 .extern_func,
439 .func,
440 .int,
441 .err,
442 .error_union,
443 .enum_literal,
444 .enum_tag,
445 .empty_enum_value,
446 .float,
447 .ptr,
448 .opt,
449 .aggregate,
450 .un,
451 // memoization, not types
452 .memoized_call,
453 => unreachable,
2277454 }
2278455 }
2279456
2280 pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value {
2281 switch (self.tag()) {
2282 .u1 => return Value.initTag(.u1_type),
2283 .u8 => return Value.initTag(.u8_type),
2284 .i8 => return Value.initTag(.i8_type),
2285 .u16 => return Value.initTag(.u16_type),
2286 .u29 => return Value.initTag(.u29_type),
2287 .i16 => return Value.initTag(.i16_type),
2288 .u32 => return Value.initTag(.u32_type),
2289 .i32 => return Value.initTag(.i32_type),
2290 .u64 => return Value.initTag(.u64_type),
2291 .i64 => return Value.initTag(.i64_type),
2292 .usize => return Value.initTag(.usize_type),
2293 .isize => return Value.initTag(.isize_type),
2294 .c_char => return Value.initTag(.c_char_type),
2295 .c_short => return Value.initTag(.c_short_type),
2296 .c_ushort => return Value.initTag(.c_ushort_type),
2297 .c_int => return Value.initTag(.c_int_type),
2298 .c_uint => return Value.initTag(.c_uint_type),
2299 .c_long => return Value.initTag(.c_long_type),
2300 .c_ulong => return Value.initTag(.c_ulong_type),
2301 .c_longlong => return Value.initTag(.c_longlong_type),
2302 .c_ulonglong => return Value.initTag(.c_ulonglong_type),
2303 .c_longdouble => return Value.initTag(.c_longdouble_type),
2304 .anyopaque => return Value.initTag(.anyopaque_type),
2305 .f16 => return Value.initTag(.f16_type),
2306 .f32 => return Value.initTag(.f32_type),
2307 .f64 => return Value.initTag(.f64_type),
2308 .f80 => return Value.initTag(.f80_type),
2309 .f128 => return Value.initTag(.f128_type),
2310 .bool => return Value.initTag(.bool_type),
2311 .void => return Value.initTag(.void_type),
2312 .type => return Value.initTag(.type_type),
2313 .anyerror => return Value.initTag(.anyerror_type),
2314 .@"anyframe" => return Value.initTag(.anyframe_type),
2315 .comptime_int => return Value.initTag(.comptime_int_type),
2316 .comptime_float => return Value.initTag(.comptime_float_type),
2317 .noreturn => return Value.initTag(.noreturn_type),
2318 .null => return Value.initTag(.null_type),
2319 .undefined => return Value.initTag(.undefined_type),
2320 .fn_noreturn_no_args => return Value.initTag(.fn_noreturn_no_args_type),
2321 .fn_void_no_args => return Value.initTag(.fn_void_no_args_type),
2322 .fn_naked_noreturn_no_args => return Value.initTag(.fn_naked_noreturn_no_args_type),
2323 .fn_ccc_void_no_args => return Value.initTag(.fn_ccc_void_no_args_type),
2324 .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type),
2325 .const_slice_u8 => return Value.initTag(.const_slice_u8_type),
2326 .const_slice_u8_sentinel_0 => return Value.initTag(.const_slice_u8_sentinel_0_type),
2327 .enum_literal => return Value.initTag(.enum_literal_type),
2328 .manyptr_u8 => return Value.initTag(.manyptr_u8_type),
2329 .manyptr_const_u8 => return Value.initTag(.manyptr_const_u8_type),
2330 .manyptr_const_u8_sentinel_0 => return Value.initTag(.manyptr_const_u8_sentinel_0_type),
2331 .atomic_order => return Value.initTag(.atomic_order_type),
2332 .atomic_rmw_op => return Value.initTag(.atomic_rmw_op_type),
2333 .calling_convention => return Value.initTag(.calling_convention_type),
2334 .address_space => return Value.initTag(.address_space_type),
2335 .float_mode => return Value.initTag(.float_mode_type),
2336 .reduce_op => return Value.initTag(.reduce_op_type),
2337 .modifier => return Value.initTag(.modifier_type),
2338 .prefetch_options => return Value.initTag(.prefetch_options_type),
2339 .export_options => return Value.initTag(.export_options_type),
2340 .extern_options => return Value.initTag(.extern_options_type),
2341 .type_info => return Value.initTag(.type_info_type),
2342 .inferred_alloc_const => unreachable,
2343 .inferred_alloc_mut => unreachable,
2344 else => return Value.Tag.ty.create(allocator, self),
2345 }
457 pub fn toIntern(ty: Type) InternPool.Index {
458 assert(ty.ip_index != .none);
459 return ty.ip_index;
460 }
461
462 pub fn toValue(self: Type) Value {
463 return self.toIntern().toValue();
2346464 }
2347465
2348466 const RuntimeBitsError = Module.CompileError || error{NeedLazy};
......@@ -2360,365 +478,319 @@ pub const Type = extern union {
2360478 /// may return false positives.
2361479 pub fn hasRuntimeBitsAdvanced(
2362480 ty: Type,
481 mod: *Module,
2363482 ignore_comptime_only: bool,
2364483 strat: AbiAlignmentAdvancedStrat,
2365484 ) RuntimeBitsError!bool {
2366 switch (ty.tag()) {
2367 .u1,
2368 .u8,
2369 .i8,
2370 .u16,
2371 .i16,
2372 .u29,
2373 .u32,
2374 .i32,
2375 .u64,
2376 .i64,
2377 .u128,
2378 .i128,
2379 .usize,
2380 .isize,
2381 .c_char,
2382 .c_short,
2383 .c_ushort,
2384 .c_int,
2385 .c_uint,
2386 .c_long,
2387 .c_ulong,
2388 .c_longlong,
2389 .c_ulonglong,
2390 .c_longdouble,
2391 .f16,
2392 .f32,
2393 .f64,
2394 .f80,
2395 .f128,
2396 .bool,
2397 .anyerror,
2398 .const_slice_u8,
2399 .const_slice_u8_sentinel_0,
2400 .array_u8_sentinel_0,
2401 .anyerror_void_error_union,
2402 .error_set_inferred,
2403 .manyptr_u8,
2404 .manyptr_const_u8,
2405 .manyptr_const_u8_sentinel_0,
2406 .atomic_order,
2407 .atomic_rmw_op,
2408 .calling_convention,
2409 .address_space,
2410 .float_mode,
2411 .reduce_op,
2412 .modifier,
2413 .prefetch_options,
2414 .export_options,
2415 .extern_options,
2416 .@"anyframe",
2417 .anyopaque,
2418 .@"opaque",
2419 .type_info,
2420 .error_set_single,
2421 .error_union,
2422 .error_set,
2423 .error_set_merged,
2424 => return true,
2425
2426 // Pointers to zero-bit types still have a runtime address; however, pointers
2427 // to comptime-only types do not, with the exception of function pointers.
2428 .anyframe_T,
2429 .optional_single_mut_pointer,
2430 .optional_single_const_pointer,
2431 .single_const_pointer,
2432 .single_mut_pointer,
2433 .many_const_pointer,
2434 .many_mut_pointer,
2435 .c_const_pointer,
2436 .c_mut_pointer,
2437 .const_slice,
2438 .mut_slice,
2439 .pointer,
2440 => {
2441 if (ignore_comptime_only) {
2442 return true;
2443 } else if (ty.childType().zigTypeTag() == .Fn) {
2444 return !ty.childType().fnInfo().is_generic;
2445 } else if (strat == .sema) {
2446 return !(try strat.sema.typeRequiresComptime(ty));
2447 } else {
2448 return !comptimeOnly(ty);
2449 }
2450 },
2451
2452 // These are false because they are comptime-only types.
2453 .single_const_pointer_to_comptime_int,
2454 .void,
2455 .type,
2456 .comptime_int,
2457 .comptime_float,
2458 .noreturn,
2459 .null,
2460 .undefined,
2461 .enum_literal,
2462 .empty_struct,
2463 .empty_struct_literal,
2464 // These are function *bodies*, not pointers.
2465 // Special exceptions have to be made when emitting functions due to
2466 // this returning false.
2467 .function,
2468 .fn_noreturn_no_args,
2469 .fn_void_no_args,
2470 .fn_naked_noreturn_no_args,
2471 .fn_ccc_void_no_args,
2472 => return false,
2473
2474 .optional => {
2475 var buf: Payload.ElemType = undefined;
2476 const child_ty = ty.optionalChild(&buf);
2477 if (child_ty.isNoReturn()) {
2478 // Then the optional is comptime-known to be null.
2479 return false;
2480 }
2481 if (ignore_comptime_only) {
2482 return true;
2483 } else if (strat == .sema) {
2484 return !(try strat.sema.typeRequiresComptime(child_ty));
2485 } else {
2486 return !comptimeOnly(child_ty);
2487 }
2488 },
2489
2490 .@"struct" => {
2491 const struct_obj = ty.castTag(.@"struct").?.data;
2492 if (struct_obj.status == .field_types_wip) {
2493 // In this case, we guess that hasRuntimeBits() for this type is true,
2494 // and then later if our guess was incorrect, we emit a compile error.
2495 struct_obj.assumed_runtime_bits = true;
2496 return true;
2497 }
2498 switch (strat) {
2499 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2500 .eager => assert(struct_obj.haveFieldTypes()),
2501 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
2502 }
2503 for (struct_obj.fields.values()) |field| {
2504 if (field.is_comptime) continue;
2505 if (try field.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
2506 return true;
2507 } else {
2508 return false;
2509 }
2510 },
2511
2512 .enum_full => {
2513 const enum_full = ty.castTag(.enum_full).?.data;
2514 return enum_full.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat);
2515 },
2516 .enum_simple => {
2517 const enum_simple = ty.castTag(.enum_simple).?.data;
2518 return enum_simple.fields.count() >= 2;
2519 },
2520 .enum_numbered, .enum_nonexhaustive => {
2521 var buffer: Payload.Bits = undefined;
2522 const int_tag_ty = ty.intTagType(&buffer);
2523 return int_tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat);
2524 },
2525
2526 .@"union" => {
2527 const union_obj = ty.castTag(.@"union").?.data;
2528 if (union_obj.status == .field_types_wip) {
2529 // In this case, we guess that hasRuntimeBits() for this type is true,
2530 // and then later if our guess was incorrect, we emit a compile error.
2531 union_obj.assumed_runtime_bits = true;
2532 return true;
2533 }
2534 switch (strat) {
2535 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2536 .eager => assert(union_obj.haveFieldTypes()),
2537 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
2538 }
2539 for (union_obj.fields.values()) |value| {
2540 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
485 return switch (ty.toIntern()) {
486 // False because it is a comptime-only type.
487 .empty_struct_type => false,
488 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
489 .int_type => |int_type| int_type.bits != 0,
490 .ptr_type => |ptr_type| {
491 // Pointers to zero-bit types still have a runtime address; however, pointers
492 // to comptime-only types do not, with the exception of function pointers.
493 if (ignore_comptime_only) return true;
494 const child_ty = ptr_type.child.toType();
495 if (child_ty.zigTypeTag(mod) == .Fn) return !mod.typeToFunc(child_ty).?.is_generic;
496 if (strat == .sema) return !(try strat.sema.typeRequiresComptime(ty));
497 return !comptimeOnly(ty, mod);
498 },
499 .anyframe_type => true,
500 .array_type => |array_type| {
501 if (array_type.sentinel != .none) {
502 return array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
503 } else {
504 return array_type.len > 0 and
505 try array_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
506 }
507 },
508 .vector_type => |vector_type| {
509 return vector_type.len > 0 and
510 try vector_type.child.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat);
511 },
512 .opt_type => |child| {
513 const child_ty = child.toType();
514 if (child_ty.isNoReturn(mod)) {
515 // Then the optional is comptime-known to be null.
516 return false;
517 }
518 if (ignore_comptime_only) {
2541519 return true;
2542 } else {
2543 return false;
2544 }
2545 },
2546 .union_safety_tagged, .union_tagged => {
2547 const union_obj = ty.cast(Payload.Union).?.data;
2548 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) {
2549 return true;
2550 }
2551
2552 switch (strat) {
2553 .sema => |sema| _ = try sema.resolveTypeFields(ty),
2554 .eager => assert(union_obj.haveFieldTypes()),
2555 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
2556 }
2557 for (union_obj.fields.values()) |value| {
2558 if (try value.ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat))
520 } else if (strat == .sema) {
521 return !(try strat.sema.typeRequiresComptime(child_ty));
522 } else {
523 return !comptimeOnly(child_ty, mod);
524 }
525 },
526 .error_union_type,
527 .error_set_type,
528 .inferred_error_set_type,
529 => true,
530
531 // These are function *bodies*, not pointers.
532 // They return false here because they are comptime-only types.
533 // Special exceptions have to be made when emitting functions due to
534 // this returning false.
535 .func_type => false,
536
537 .simple_type => |t| switch (t) {
538 .f16,
539 .f32,
540 .f64,
541 .f80,
542 .f128,
543 .usize,
544 .isize,
545 .c_char,
546 .c_short,
547 .c_ushort,
548 .c_int,
549 .c_uint,
550 .c_long,
551 .c_ulong,
552 .c_longlong,
553 .c_ulonglong,
554 .c_longdouble,
555 .bool,
556 .anyerror,
557 .anyopaque,
558 .atomic_order,
559 .atomic_rmw_op,
560 .calling_convention,
561 .address_space,
562 .float_mode,
563 .reduce_op,
564 .call_modifier,
565 .prefetch_options,
566 .export_options,
567 .extern_options,
568 => true,
569
570 // These are false because they are comptime-only types.
571 .void,
572 .type,
573 .comptime_int,
574 .comptime_float,
575 .noreturn,
576 .null,
577 .undefined,
578 .enum_literal,
579 .type_info,
580 => false,
581
582 .generic_poison => unreachable,
583 },
584 .struct_type => |struct_type| {
585 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
586 // This struct has no fields.
587 return false;
588 };
589 if (struct_obj.status == .field_types_wip) {
590 // In this case, we guess that hasRuntimeBits() for this type is true,
591 // and then later if our guess was incorrect, we emit a compile error.
592 struct_obj.assumed_runtime_bits = true;
2559593 return true;
2560 } else {
594 }
595 switch (strat) {
596 .sema => |sema| _ = try sema.resolveTypeFields(ty),
597 .eager => assert(struct_obj.haveFieldTypes()),
598 .lazy => if (!struct_obj.haveFieldTypes()) return error.NeedLazy,
599 }
600 for (struct_obj.fields.values()) |field| {
601 if (field.is_comptime) continue;
602 if (try field.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
603 return true;
604 } else {
605 return false;
606 }
607 },
608 .anon_struct_type => |tuple| {
609 for (tuple.types, tuple.values) |field_ty, val| {
610 if (val != .none) continue; // comptime field
611 if (try field_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) return true;
612 }
2561613 return false;
2562 }
2563 },
2564
2565 .array, .vector => return ty.arrayLen() != 0 and
2566 try ty.elemType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat),
2567 .array_u8 => return ty.arrayLen() != 0,
2568 .array_sentinel => return ty.childType().hasRuntimeBitsAdvanced(ignore_comptime_only, strat),
614 },
2569615
2570 .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data != 0,
616 .union_type => |union_type| {
617 const union_obj = mod.unionPtr(union_type.index);
618 switch (union_type.runtime_tag) {
619 .none => {
620 if (union_obj.status == .field_types_wip) {
621 // In this case, we guess that hasRuntimeBits() for this type is true,
622 // and then later if our guess was incorrect, we emit a compile error.
623 union_obj.assumed_runtime_bits = true;
624 return true;
625 }
626 },
627 .safety, .tagged => {
628 if (try union_obj.tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat)) {
629 return true;
630 }
631 },
632 }
633 switch (strat) {
634 .sema => |sema| _ = try sema.resolveTypeFields(ty),
635 .eager => assert(union_obj.haveFieldTypes()),
636 .lazy => if (!union_obj.haveFieldTypes()) return error.NeedLazy,
637 }
638 for (union_obj.fields.values()) |value| {
639 if (try value.ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat))
640 return true;
641 } else {
642 return false;
643 }
644 },
2571645
2572 .tuple, .anon_struct => {
2573 const tuple = ty.tupleFields();
2574 for (tuple.types, 0..) |field_ty, i| {
2575 const val = tuple.values[i];
2576 if (val.tag() != .unreachable_value) continue; // comptime field
2577 if (try field_ty.hasRuntimeBitsAdvanced(ignore_comptime_only, strat)) return true;
2578 }
2579 return false;
646 .opaque_type => true,
647 .enum_type => |enum_type| enum_type.tag_ty.toType().hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat),
648
649 // values, not types
650 .undef,
651 .runtime_value,
652 .simple_value,
653 .variable,
654 .extern_func,
655 .func,
656 .int,
657 .err,
658 .error_union,
659 .enum_literal,
660 .enum_tag,
661 .empty_enum_value,
662 .float,
663 .ptr,
664 .opt,
665 .aggregate,
666 .un,
667 // memoization, not types
668 .memoized_call,
669 => unreachable,
2580670 },
2581
2582 .inferred_alloc_const => unreachable,
2583 .inferred_alloc_mut => unreachable,
2584 .generic_poison => unreachable,
2585 }
671 };
2586672 }
2587673
2588674 /// true if and only if the type has a well-defined memory layout
2589675 /// readFrom/writeToMemory are supported only for types with a well-
2590676 /// defined memory layout
2591 pub fn hasWellDefinedLayout(ty: Type) bool {
2592 return switch (ty.tag()) {
2593 .u1,
2594 .u8,
2595 .i8,
2596 .u16,
2597 .i16,
2598 .u29,
2599 .u32,
2600 .i32,
2601 .u64,
2602 .i64,
2603 .u128,
2604 .i128,
2605 .usize,
2606 .isize,
2607 .c_char,
2608 .c_short,
2609 .c_ushort,
2610 .c_int,
2611 .c_uint,
2612 .c_long,
2613 .c_ulong,
2614 .c_longlong,
2615 .c_ulonglong,
2616 .c_longdouble,
2617 .f16,
2618 .f32,
2619 .f64,
2620 .f80,
2621 .f128,
2622 .bool,
2623 .void,
2624 .manyptr_u8,
2625 .manyptr_const_u8,
2626 .manyptr_const_u8_sentinel_0,
2627 .array_u8,
2628 .array_u8_sentinel_0,
2629 .int_signed,
2630 .int_unsigned,
2631 .pointer,
2632 .single_const_pointer,
2633 .single_mut_pointer,
2634 .many_const_pointer,
2635 .many_mut_pointer,
2636 .c_const_pointer,
2637 .c_mut_pointer,
2638 .single_const_pointer_to_comptime_int,
2639 .enum_numbered,
2640 .vector,
2641 .optional_single_mut_pointer,
2642 .optional_single_const_pointer,
677 pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
678 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
679 .int_type,
680 .vector_type,
2643681 => true,
2644682
2645 .anyopaque,
2646 .anyerror,
2647 .noreturn,
2648 .null,
2649 .@"anyframe",
2650 .undefined,
2651 .atomic_order,
2652 .atomic_rmw_op,
2653 .calling_convention,
2654 .address_space,
2655 .float_mode,
2656 .reduce_op,
2657 .modifier,
2658 .prefetch_options,
2659 .export_options,
2660 .extern_options,
2661 .error_set,
2662 .error_set_single,
2663 .error_set_inferred,
2664 .error_set_merged,
2665 .@"opaque",
2666 .generic_poison,
2667 .type,
2668 .comptime_int,
2669 .comptime_float,
2670 .enum_literal,
2671 .type_info,
683 .error_union_type,
684 .error_set_type,
685 .inferred_error_set_type,
686 .anon_struct_type,
687 .opaque_type,
688 .anyframe_type,
2672689 // These are function bodies, not function pointers.
2673 .fn_noreturn_no_args,
2674 .fn_void_no_args,
2675 .fn_naked_noreturn_no_args,
2676 .fn_ccc_void_no_args,
2677 .function,
2678 .const_slice_u8,
2679 .const_slice_u8_sentinel_0,
2680 .const_slice,
2681 .mut_slice,
2682 .enum_simple,
2683 .error_union,
2684 .anyerror_void_error_union,
2685 .anyframe_T,
2686 .tuple,
2687 .anon_struct,
2688 .empty_struct_literal,
2689 .empty_struct,
690 .func_type,
2690691 => false,
2691692
2692 .enum_full,
2693 .enum_nonexhaustive,
2694 => !ty.cast(Payload.EnumFull).?.data.tag_ty_inferred,
2695
2696 .inferred_alloc_mut => unreachable,
2697 .inferred_alloc_const => unreachable,
693 .array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
694 .opt_type => ty.isPtrLikeOptional(mod),
695 .ptr_type => |ptr_type| ptr_type.flags.size != .Slice,
2698696
2699 .array,
2700 .array_sentinel,
2701 => ty.childType().hasWellDefinedLayout(),
697 .simple_type => |t| switch (t) {
698 .f16,
699 .f32,
700 .f64,
701 .f80,
702 .f128,
703 .usize,
704 .isize,
705 .c_char,
706 .c_short,
707 .c_ushort,
708 .c_int,
709 .c_uint,
710 .c_long,
711 .c_ulong,
712 .c_longlong,
713 .c_ulonglong,
714 .c_longdouble,
715 .bool,
716 .void,
717 => true,
2702718
2703 .optional => ty.isPtrLikeOptional(),
2704 .@"struct" => ty.castTag(.@"struct").?.data.layout != .Auto,
2705 .@"union", .union_safety_tagged => ty.cast(Payload.Union).?.data.layout != .Auto,
2706 .union_tagged => false,
719 .anyerror,
720 .anyopaque,
721 .atomic_order,
722 .atomic_rmw_op,
723 .calling_convention,
724 .address_space,
725 .float_mode,
726 .reduce_op,
727 .call_modifier,
728 .prefetch_options,
729 .export_options,
730 .extern_options,
731 .type,
732 .comptime_int,
733 .comptime_float,
734 .noreturn,
735 .null,
736 .undefined,
737 .enum_literal,
738 .type_info,
739 .generic_poison,
740 => false,
741 },
742 .struct_type => |struct_type| {
743 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse {
744 // Struct with no fields has a well-defined layout of no bits.
745 return true;
746 };
747 return struct_obj.layout != .Auto;
748 },
749 .union_type => |union_type| switch (union_type.runtime_tag) {
750 .none, .safety => mod.unionPtr(union_type.index).layout != .Auto,
751 .tagged => false,
752 },
753 .enum_type => |enum_type| switch (enum_type.tag_mode) {
754 .auto => false,
755 .explicit, .nonexhaustive => true,
756 },
757
758 // values, not types
759 .undef,
760 .runtime_value,
761 .simple_value,
762 .variable,
763 .extern_func,
764 .func,
765 .int,
766 .err,
767 .error_union,
768 .enum_literal,
769 .enum_tag,
770 .empty_enum_value,
771 .float,
772 .ptr,
773 .opt,
774 .aggregate,
775 .un,
776 // memoization, not types
777 .memoized_call,
778 => unreachable,
2707779 };
2708780 }
2709781
2710 pub fn hasRuntimeBits(ty: Type) bool {
2711 return hasRuntimeBitsAdvanced(ty, false, .eager) catch unreachable;
782 pub fn hasRuntimeBits(ty: Type, mod: *Module) bool {
783 return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable;
2712784 }
2713785
2714 pub fn hasRuntimeBitsIgnoreComptime(ty: Type) bool {
2715 return hasRuntimeBitsAdvanced(ty, true, .eager) catch unreachable;
786 pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
787 return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable;
2716788 }
2717789
2718 pub fn isFnOrHasRuntimeBits(ty: Type) bool {
2719 switch (ty.zigTypeTag()) {
790 pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool {
791 switch (ty.zigTypeTag(mod)) {
2720792 .Fn => {
2721 const fn_info = ty.fnInfo();
793 const fn_info = mod.typeToFunc(ty).?;
2722794 if (fn_info.is_generic) return false;
2723795 if (fn_info.is_var_args) return true;
2724796 switch (fn_info.cc) {
......@@ -2727,131 +799,66 @@ pub const Type = extern union {
2727799 .Inline => return false,
2728800 else => {},
2729801 }
2730 if (fn_info.return_type.comptimeOnly()) return false;
802 if (fn_info.return_type.toType().comptimeOnly(mod)) return false;
2731803 return true;
2732804 },
2733 else => return ty.hasRuntimeBits(),
805 else => return ty.hasRuntimeBits(mod),
2734806 }
2735807 }
2736808
2737809 /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive.
2738 pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type) bool {
2739 return switch (ty.zigTypeTag()) {
810 pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool {
811 return switch (ty.zigTypeTag(mod)) {
2740812 .Fn => true,
2741 else => return ty.hasRuntimeBitsIgnoreComptime(),
813 else => return ty.hasRuntimeBitsIgnoreComptime(mod),
2742814 };
2743815 }
2744816
2745 /// TODO add enums with no fields here
2746 pub fn isNoReturn(ty: Type) bool {
2747 switch (ty.tag()) {
2748 .noreturn => return true,
2749 .error_set => {
2750 const err_set_obj = ty.castTag(.error_set).?.data;
2751 const names = err_set_obj.names.keys();
2752 return names.len == 0;
2753 },
2754 .error_set_merged => {
2755 const name_map = ty.castTag(.error_set_merged).?.data;
2756 const names = name_map.keys();
2757 return names.len == 0;
2758 },
2759 else => return false,
2760 }
817 pub fn isNoReturn(ty: Type, mod: *Module) bool {
818 return mod.intern_pool.isNoReturn(ty.toIntern());
2761819 }
2762820
2763821 /// Returns 0 if the pointer is naturally aligned and the element type is 0-bit.
2764 pub fn ptrAlignment(ty: Type, target: Target) u32 {
2765 return ptrAlignmentAdvanced(ty, target, null) catch unreachable;
2766 }
2767
2768 pub fn ptrAlignmentAdvanced(ty: Type, target: Target, opt_sema: ?*Sema) !u32 {
2769 switch (ty.tag()) {
2770 .single_const_pointer,
2771 .single_mut_pointer,
2772 .many_const_pointer,
2773 .many_mut_pointer,
2774 .c_const_pointer,
2775 .c_mut_pointer,
2776 .const_slice,
2777 .mut_slice,
2778 .optional_single_const_pointer,
2779 .optional_single_mut_pointer,
2780 => {
2781 const child_type = ty.cast(Payload.ElemType).?.data;
2782 if (opt_sema) |sema| {
2783 const res = try child_type.abiAlignmentAdvanced(target, .{ .sema = sema });
2784 return res.scalar;
2785 }
2786 return (child_type.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;
2787 },
822 pub fn ptrAlignment(ty: Type, mod: *Module) u32 {
823 return ptrAlignmentAdvanced(ty, mod, null) catch unreachable;
824 }
2788825
2789 .manyptr_u8,
2790 .manyptr_const_u8,
2791 .manyptr_const_u8_sentinel_0,
2792 .const_slice_u8,
2793 .const_slice_u8_sentinel_0,
2794 => return 1,
2795
2796 .pointer => {
2797 const ptr_info = ty.castTag(.pointer).?.data;
2798 if (ptr_info.@"align" != 0) {
2799 return ptr_info.@"align";
826 pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !u32 {
827 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
828 .ptr_type => |ptr_type| {
829 if (ptr_type.flags.alignment.toByteUnitsOptional()) |a| {
830 return @intCast(u32, a);
2800831 } else if (opt_sema) |sema| {
2801 const res = try ptr_info.pointee_type.abiAlignmentAdvanced(target, .{ .sema = sema });
832 const res = try ptr_type.child.toType().abiAlignmentAdvanced(mod, .{ .sema = sema });
2802833 return res.scalar;
2803834 } else {
2804 return (ptr_info.pointee_type.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;
835 return (ptr_type.child.toType().abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
2805836 }
2806837 },
2807 .optional => return ty.castTag(.optional).?.data.ptrAlignmentAdvanced(target, opt_sema),
2808
838 .opt_type => |child| child.toType().ptrAlignmentAdvanced(mod, opt_sema),
2809839 else => unreachable,
2810 }
840 };
2811841 }
2812842
2813 pub fn ptrAddressSpace(self: Type) std.builtin.AddressSpace {
2814 return switch (self.tag()) {
2815 .single_const_pointer_to_comptime_int,
2816 .const_slice_u8,
2817 .const_slice_u8_sentinel_0,
2818 .single_const_pointer,
2819 .single_mut_pointer,
2820 .many_const_pointer,
2821 .many_mut_pointer,
2822 .c_const_pointer,
2823 .c_mut_pointer,
2824 .const_slice,
2825 .mut_slice,
2826 .inferred_alloc_const,
2827 .inferred_alloc_mut,
2828 .manyptr_u8,
2829 .manyptr_const_u8,
2830 .manyptr_const_u8_sentinel_0,
2831 => .generic,
2832
2833 .pointer => self.castTag(.pointer).?.data.@"addrspace",
2834
2835 .optional => {
2836 var buf: Payload.ElemType = undefined;
2837 const child_type = self.optionalChild(&buf);
2838 return child_type.ptrAddressSpace();
2839 },
2840
843 pub fn ptrAddressSpace(ty: Type, mod: *const Module) std.builtin.AddressSpace {
844 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
845 .ptr_type => |ptr_type| ptr_type.flags.address_space,
846 .opt_type => |child| mod.intern_pool.indexToKey(child).ptr_type.flags.address_space,
2841847 else => unreachable,
2842848 };
2843849 }
2844850
2845851 /// Returns 0 for 0-bit types.
2846 pub fn abiAlignment(ty: Type, target: Target) u32 {
2847 return (ty.abiAlignmentAdvanced(target, .eager) catch unreachable).scalar;
852 pub fn abiAlignment(ty: Type, mod: *Module) u32 {
853 return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar;
2848854 }
2849855
2850856 /// May capture a reference to `ty`.
2851 pub fn lazyAbiAlignment(ty: Type, target: Target, arena: Allocator) !Value {
2852 switch (try ty.abiAlignmentAdvanced(target, .{ .lazy = arena })) {
857 /// Returned value has type `comptime_int`.
858 pub fn lazyAbiAlignment(ty: Type, mod: *Module) !Value {
859 switch (try ty.abiAlignmentAdvanced(mod, .lazy)) {
2853860 .val => |val| return val,
2854 .scalar => |x| return Value.Tag.int_u64.create(arena, x),
861 .scalar => |x| return mod.intValue(Type.comptime_int, x),
2855862 }
2856863 }
2857864
......@@ -2862,7 +869,7 @@ pub const Type = extern union {
2862869
2863870 pub const AbiAlignmentAdvancedStrat = union(enum) {
2864871 eager,
2865 lazy: Allocator,
872 lazy,
2866873 sema: *Sema,
2867874 };
2868875
......@@ -2874,314 +881,322 @@ pub const Type = extern union {
2874881 /// necessary, possibly returning a CompileError.
2875882 pub fn abiAlignmentAdvanced(
2876883 ty: Type,
2877 target: Target,
884 mod: *Module,
2878885 strat: AbiAlignmentAdvancedStrat,
2879886 ) Module.CompileError!AbiAlignmentAdvanced {
887 const target = mod.getTarget();
888
2880889 const opt_sema = switch (strat) {
2881890 .sema => |sema| sema,
2882891 else => null,
2883892 };
2884 switch (ty.tag()) {
2885 .u1,
2886 .u8,
2887 .i8,
2888 .bool,
2889 .array_u8_sentinel_0,
2890 .array_u8,
2891 .atomic_order,
2892 .atomic_rmw_op,
2893 .calling_convention,
2894 .address_space,
2895 .float_mode,
2896 .reduce_op,
2897 .modifier,
2898 .prefetch_options,
2899 .export_options,
2900 .extern_options,
2901 .@"opaque",
2902 .anyopaque,
2903 => return AbiAlignmentAdvanced{ .scalar = 1 },
2904
2905 .fn_noreturn_no_args, // represents machine code; not a pointer
2906 .fn_void_no_args, // represents machine code; not a pointer
2907 .fn_naked_noreturn_no_args, // represents machine code; not a pointer
2908 .fn_ccc_void_no_args, // represents machine code; not a pointer
2909 => return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) },
2910
2911 // represents machine code; not a pointer
2912 .function => {
2913 const alignment = ty.castTag(.function).?.data.alignment;
2914 if (alignment != 0) return AbiAlignmentAdvanced{ .scalar = alignment };
2915 return AbiAlignmentAdvanced{ .scalar = target_util.defaultFunctionAlignment(target) };
2916 },
2917893
2918 .isize,
2919 .usize,
2920 .single_const_pointer_to_comptime_int,
2921 .const_slice_u8,
2922 .const_slice_u8_sentinel_0,
2923 .single_const_pointer,
2924 .single_mut_pointer,
2925 .many_const_pointer,
2926 .many_mut_pointer,
2927 .c_const_pointer,
2928 .c_mut_pointer,
2929 .const_slice,
2930 .mut_slice,
2931 .optional_single_const_pointer,
2932 .optional_single_mut_pointer,
2933 .pointer,
2934 .manyptr_u8,
2935 .manyptr_const_u8,
2936 .manyptr_const_u8_sentinel_0,
2937 .@"anyframe",
2938 .anyframe_T,
2939 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
2940
2941 .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) },
2942 .c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) },
2943 .c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) },
2944 .c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) },
2945 .c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) },
2946 .c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) },
2947 .c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) },
2948 .c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) },
2949 .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) },
2950 .c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2951
2952 .f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
2953 .f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) },
2954 .f64 => switch (target.c_type_bit_size(.double)) {
2955 64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) },
2956 else => return AbiAlignmentAdvanced{ .scalar = 8 },
2957 },
2958 .f80 => switch (target.c_type_bit_size(.longdouble)) {
2959 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2960 else => {
2961 var payload: Payload.Bits = .{
2962 .base = .{ .tag = .int_unsigned },
2963 .data = 80,
2964 };
2965 const u80_ty = initPayload(&payload.base);
2966 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, target) };
894 switch (ty.toIntern()) {
895 .empty_struct_type => return AbiAlignmentAdvanced{ .scalar = 0 },
896 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
897 .int_type => |int_type| {
898 if (int_type.bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
899 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(int_type.bits, target) };
900 },
901 .ptr_type, .anyframe_type => {
902 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
903 },
904 .array_type => |array_type| {
905 return array_type.child.toType().abiAlignmentAdvanced(mod, strat);
906 },
907 .vector_type => |vector_type| {
908 const bits_u64 = try bitSizeAdvanced(vector_type.child.toType(), mod, opt_sema);
909 const bits = @intCast(u32, bits_u64);
910 const bytes = ((bits * vector_type.len) + 7) / 8;
911 const alignment = std.math.ceilPowerOfTwoAssert(u32, bytes);
912 return AbiAlignmentAdvanced{ .scalar = alignment };
2967913 },
2968 },
2969 .f128 => switch (target.c_type_bit_size(.longdouble)) {
2970 128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
2971 else => return AbiAlignmentAdvanced{ .scalar = 16 },
2972 },
2973
2974 // TODO revisit this when we have the concept of the error tag type
2975 .anyerror_void_error_union,
2976 .anyerror,
2977 .error_set_inferred,
2978 .error_set_single,
2979 .error_set,
2980 .error_set_merged,
2981 => return AbiAlignmentAdvanced{ .scalar = 2 },
2982
2983 .array, .array_sentinel => return ty.elemType().abiAlignmentAdvanced(target, strat),
2984
2985 .vector => {
2986 const len = ty.arrayLen();
2987 const bits = try bitSizeAdvanced(ty.elemType(), target, opt_sema);
2988 const bytes = ((bits * len) + 7) / 8;
2989 const alignment = std.math.ceilPowerOfTwoAssert(u64, bytes);
2990 return AbiAlignmentAdvanced{ .scalar = @intCast(u32, alignment) };
2991 },
2992
2993 .i16, .u16 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(16, target) },
2994 .u29 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(29, target) },
2995 .i32, .u32 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(32, target) },
2996 .i64, .u64 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(64, target) },
2997 .u128, .i128 => return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(128, target) },
2998914
2999 .int_signed, .int_unsigned => {
3000 const bits: u16 = ty.cast(Payload.Bits).?.data;
3001 if (bits == 0) return AbiAlignmentAdvanced{ .scalar = 0 };
3002 return AbiAlignmentAdvanced{ .scalar = intAbiAlignment(bits, target) };
3003 },
915 .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
916 .error_union_type => |info| return abiAlignmentAdvancedErrorUnion(ty, mod, strat, info.payload_type.toType()),
3004917
3005 .optional => {
3006 var buf: Payload.ElemType = undefined;
3007 const child_type = ty.optionalChild(&buf);
918 // TODO revisit this when we have the concept of the error tag type
919 .error_set_type, .inferred_error_set_type => return AbiAlignmentAdvanced{ .scalar = 2 },
3008920
3009 switch (child_type.zigTypeTag()) {
3010 .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3011 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, target, strat),
3012 .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },
3013 else => {},
3014 }
921 // represents machine code; not a pointer
922 .func_type => |func_type| return AbiAlignmentAdvanced{
923 .scalar = if (func_type.alignment.toByteUnitsOptional()) |a|
924 @intCast(u32, a)
925 else
926 target_util.defaultFunctionAlignment(target),
927 },
3015928
3016 switch (strat) {
3017 .eager, .sema => {
3018 if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3019 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
3020 else => |e| return e,
3021 })) {
3022 return AbiAlignmentAdvanced{ .scalar = 1 };
3023 }
3024 return child_type.abiAlignmentAdvanced(target, strat);
929 .simple_type => |t| switch (t) {
930 .bool,
931 .atomic_order,
932 .atomic_rmw_op,
933 .calling_convention,
934 .address_space,
935 .float_mode,
936 .reduce_op,
937 .call_modifier,
938 .prefetch_options,
939 .anyopaque,
940 => return AbiAlignmentAdvanced{ .scalar = 1 },
941
942 .usize,
943 .isize,
944 .export_options,
945 .extern_options,
946 => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
947
948 .c_char => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.char) },
949 .c_short => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.short) },
950 .c_ushort => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ushort) },
951 .c_int => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.int) },
952 .c_uint => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.uint) },
953 .c_long => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.long) },
954 .c_ulong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulong) },
955 .c_longlong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longlong) },
956 .c_ulonglong => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.ulonglong) },
957 .c_longdouble => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
958
959 .f16 => return AbiAlignmentAdvanced{ .scalar = 2 },
960 .f32 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.float) },
961 .f64 => switch (target.c_type_bit_size(.double)) {
962 64 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.double) },
963 else => return AbiAlignmentAdvanced{ .scalar = 8 },
3025964 },
3026 .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(target, strat)) {
3027 .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },
3028 .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
965 .f80 => switch (target.c_type_bit_size(.longdouble)) {
966 80 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
967 else => {
968 const u80_ty: Type = .{ .ip_index = .u80_type };
969 return AbiAlignmentAdvanced{ .scalar = abiAlignment(u80_ty, mod) };
970 },
971 },
972 .f128 => switch (target.c_type_bit_size(.longdouble)) {
973 128 => return AbiAlignmentAdvanced{ .scalar = target.c_type_alignment(.longdouble) },
974 else => return AbiAlignmentAdvanced{ .scalar = 16 },
3029975 },
3030 }
3031 },
3032976
3033 .error_union => {
3034 // This code needs to be kept in sync with the equivalent switch prong
3035 // in abiSizeAdvanced.
3036 const data = ty.castTag(.error_union).?.data;
3037 const code_align = abiAlignment(Type.anyerror, target);
3038 switch (strat) {
3039 .eager, .sema => {
3040 if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3041 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
3042 else => |e| return e,
3043 })) {
3044 return AbiAlignmentAdvanced{ .scalar = code_align };
977 // TODO revisit this when we have the concept of the error tag type
978 .anyerror => return AbiAlignmentAdvanced{ .scalar = 2 },
979
980 .void,
981 .type,
982 .comptime_int,
983 .comptime_float,
984 .null,
985 .undefined,
986 .enum_literal,
987 .type_info,
988 => return AbiAlignmentAdvanced{ .scalar = 0 },
989
990 .noreturn => unreachable,
991 .generic_poison => unreachable,
992 },
993 .struct_type => |struct_type| {
994 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
995 return AbiAlignmentAdvanced{ .scalar = 0 };
996
997 if (opt_sema) |sema| {
998 if (struct_obj.status == .field_types_wip) {
999 // We'll guess "pointer-aligned", if the struct has an
1000 // underaligned pointer field then some allocations
1001 // might require explicit alignment.
1002 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
30451003 }
3046 return AbiAlignmentAdvanced{ .scalar = @max(
3047 code_align,
3048 (try data.payload.abiAlignmentAdvanced(target, strat)).scalar,
3049 ) };
3050 },
3051 .lazy => |arena| {
3052 switch (try data.payload.abiAlignmentAdvanced(target, strat)) {
3053 .scalar => |payload_align| {
3054 return AbiAlignmentAdvanced{
3055 .scalar = @max(code_align, payload_align),
3056 };
3057 },
3058 .val => {},
1004 _ = try sema.resolveTypeFields(ty);
1005 }
1006 if (!struct_obj.haveFieldTypes()) switch (strat) {
1007 .eager => unreachable, // struct layout not resolved
1008 .sema => unreachable, // handled above
1009 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1010 .ty = .comptime_int_type,
1011 .storage = .{ .lazy_align = ty.toIntern() },
1012 } })).toValue() },
1013 };
1014 if (struct_obj.layout == .Packed) {
1015 switch (strat) {
1016 .sema => |sema| try sema.resolveTypeLayout(ty),
1017 .lazy => if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1018 .ty = .comptime_int_type,
1019 .storage = .{ .lazy_align = ty.toIntern() },
1020 } })).toValue() },
1021 .eager => {},
30591022 }
3060 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
3061 },
3062 }
3063 },
3064
3065 .@"struct" => {
3066 const struct_obj = ty.castTag(.@"struct").?.data;
3067 if (opt_sema) |sema| {
3068 if (struct_obj.status == .field_types_wip) {
3069 // We'll guess "pointer-aligned", if the struct has an
3070 // underaligned pointer field then some allocations
3071 // might require explicit alignment.
3072 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
1023 assert(struct_obj.haveLayout());
1024 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(mod) };
30731025 }
3074 _ = try sema.resolveTypeFields(ty);
3075 }
3076 if (!struct_obj.haveFieldTypes()) switch (strat) {
3077 .eager => unreachable, // struct layout not resolved
3078 .sema => unreachable, // handled above
3079 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
3080 };
3081 if (struct_obj.layout == .Packed) {
3082 switch (strat) {
3083 .sema => |sema| try sema.resolveTypeLayout(ty),
3084 .lazy => |arena| {
3085 if (!struct_obj.haveLayout()) {
3086 return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
1026
1027 const fields = ty.structFields(mod);
1028 var big_align: u32 = 0;
1029 for (fields.values()) |field| {
1030 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1031 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1032 .ty = .comptime_int_type,
1033 .storage = .{ .lazy_align = ty.toIntern() },
1034 } })).toValue() },
1035 else => |e| return e,
1036 })) continue;
1037
1038 const field_align = if (field.abi_align != 0)
1039 field.abi_align
1040 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
1041 .scalar => |a| a,
1042 .val => switch (strat) {
1043 .eager => unreachable, // struct layout not resolved
1044 .sema => unreachable, // handled above
1045 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1046 .ty = .comptime_int_type,
1047 .storage = .{ .lazy_align = ty.toIntern() },
1048 } })).toValue() },
1049 },
1050 };
1051 big_align = @max(big_align, field_align);
1052
1053 // This logic is duplicated in Module.Struct.Field.alignment.
1054 if (struct_obj.layout == .Extern or target.ofmt == .c) {
1055 if (field.ty.isAbiInt(mod) and field.ty.intInfo(mod).bits >= 128) {
1056 // The C ABI requires 128 bit integer fields of structs
1057 // to be 16-bytes aligned.
1058 big_align = @max(big_align, 16);
30871059 }
3088 },
3089 .eager => {},
1060 }
30901061 }
3091 assert(struct_obj.haveLayout());
3092 return AbiAlignmentAdvanced{ .scalar = struct_obj.backing_int_ty.abiAlignment(target) };
3093 }
3094
3095 const fields = ty.structFields();
3096 var big_align: u32 = 0;
3097 for (fields.values()) |field| {
3098 if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3099 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
3100 else => |e| return e,
3101 })) continue;
3102
3103 const field_align = if (field.abi_align != 0)
3104 field.abi_align
3105 else switch (try field.ty.abiAlignmentAdvanced(target, strat)) {
3106 .scalar => |a| a,
3107 .val => switch (strat) {
3108 .eager => unreachable, // struct layout not resolved
3109 .sema => unreachable, // handled above
3110 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
3111 },
3112 };
3113 big_align = @max(big_align, field_align);
3114
3115 // This logic is duplicated in Module.Struct.Field.alignment.
3116 if (struct_obj.layout == .Extern or target.ofmt == .c) {
3117 if (field.ty.isAbiInt() and field.ty.intInfo(target).bits >= 128) {
3118 // The C ABI requires 128 bit integer fields of structs
3119 // to be 16-bytes aligned.
3120 big_align = @max(big_align, 16);
1062 return AbiAlignmentAdvanced{ .scalar = big_align };
1063 },
1064 .anon_struct_type => |tuple| {
1065 var big_align: u32 = 0;
1066 for (tuple.types, tuple.values) |field_ty, val| {
1067 if (val != .none) continue; // comptime field
1068 if (!(field_ty.toType().hasRuntimeBits(mod))) continue;
1069
1070 switch (try field_ty.toType().abiAlignmentAdvanced(mod, strat)) {
1071 .scalar => |field_align| big_align = @max(big_align, field_align),
1072 .val => switch (strat) {
1073 .eager => unreachable, // field type alignment not resolved
1074 .sema => unreachable, // passed to abiAlignmentAdvanced above
1075 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1076 .ty = .comptime_int_type,
1077 .storage = .{ .lazy_align = ty.toIntern() },
1078 } })).toValue() },
1079 },
31211080 }
31221081 }
3123 }
3124 return AbiAlignmentAdvanced{ .scalar = big_align };
3125 },
3126
3127 .tuple, .anon_struct => {
3128 const tuple = ty.tupleFields();
3129 var big_align: u32 = 0;
3130 for (tuple.types, 0..) |field_ty, i| {
3131 const val = tuple.values[i];
3132 if (val.tag() != .unreachable_value) continue; // comptime field
3133 if (!(field_ty.hasRuntimeBits())) continue;
1082 return AbiAlignmentAdvanced{ .scalar = big_align };
1083 },
31341084
3135 switch (try field_ty.abiAlignmentAdvanced(target, strat)) {
3136 .scalar => |field_align| big_align = @max(big_align, field_align),
3137 .val => switch (strat) {
3138 .eager => unreachable, // field type alignment not resolved
3139 .sema => unreachable, // passed to abiAlignmentAdvanced above
3140 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
3141 },
3142 }
3143 }
3144 return AbiAlignmentAdvanced{ .scalar = big_align };
1085 .union_type => |union_type| {
1086 const union_obj = mod.unionPtr(union_type.index);
1087 return abiAlignmentAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
1088 },
1089 .opaque_type => return AbiAlignmentAdvanced{ .scalar = 1 },
1090 .enum_type => |enum_type| return AbiAlignmentAdvanced{ .scalar = enum_type.tag_ty.toType().abiAlignment(mod) },
1091
1092 // values, not types
1093 .undef,
1094 .runtime_value,
1095 .simple_value,
1096 .variable,
1097 .extern_func,
1098 .func,
1099 .int,
1100 .err,
1101 .error_union,
1102 .enum_literal,
1103 .enum_tag,
1104 .empty_enum_value,
1105 .float,
1106 .ptr,
1107 .opt,
1108 .aggregate,
1109 .un,
1110 // memoization, not types
1111 .memoized_call,
1112 => unreachable,
31451113 },
1114 }
1115 }
31461116
3147 .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => {
3148 var buffer: Payload.Bits = undefined;
3149 const int_tag_ty = ty.intTagType(&buffer);
3150 return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(target) };
3151 },
3152 .@"union" => {
3153 const union_obj = ty.castTag(.@"union").?.data;
3154 return abiAlignmentAdvancedUnion(ty, target, strat, union_obj, false);
3155 },
3156 .union_safety_tagged, .union_tagged => {
3157 const union_obj = ty.cast(Payload.Union).?.data;
3158 return abiAlignmentAdvancedUnion(ty, target, strat, union_obj, true);
1117 fn abiAlignmentAdvancedErrorUnion(
1118 ty: Type,
1119 mod: *Module,
1120 strat: AbiAlignmentAdvancedStrat,
1121 payload_ty: Type,
1122 ) Module.CompileError!AbiAlignmentAdvanced {
1123 // This code needs to be kept in sync with the equivalent switch prong
1124 // in abiSizeAdvanced.
1125 const code_align = abiAlignment(Type.anyerror, mod);
1126 switch (strat) {
1127 .eager, .sema => {
1128 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1129 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1130 .ty = .comptime_int_type,
1131 .storage = .{ .lazy_align = ty.toIntern() },
1132 } })).toValue() },
1133 else => |e| return e,
1134 })) {
1135 return AbiAlignmentAdvanced{ .scalar = code_align };
1136 }
1137 return AbiAlignmentAdvanced{ .scalar = @max(
1138 code_align,
1139 (try payload_ty.abiAlignmentAdvanced(mod, strat)).scalar,
1140 ) };
1141 },
1142 .lazy => {
1143 switch (try payload_ty.abiAlignmentAdvanced(mod, strat)) {
1144 .scalar => |payload_align| {
1145 return AbiAlignmentAdvanced{
1146 .scalar = @max(code_align, payload_align),
1147 };
1148 },
1149 .val => {},
1150 }
1151 return .{ .val = (try mod.intern(.{ .int = .{
1152 .ty = .comptime_int_type,
1153 .storage = .{ .lazy_align = ty.toIntern() },
1154 } })).toValue() };
31591155 },
1156 }
1157 }
31601158
3161 .empty_struct,
3162 .void,
3163 .empty_struct_literal,
3164 .type,
3165 .comptime_int,
3166 .comptime_float,
3167 .null,
3168 .undefined,
3169 .enum_literal,
3170 .type_info,
3171 => return AbiAlignmentAdvanced{ .scalar = 0 },
1159 fn abiAlignmentAdvancedOptional(
1160 ty: Type,
1161 mod: *Module,
1162 strat: AbiAlignmentAdvancedStrat,
1163 ) Module.CompileError!AbiAlignmentAdvanced {
1164 const target = mod.getTarget();
1165 const child_type = ty.optionalChild(mod);
31721166
3173 .noreturn,
3174 .inferred_alloc_const,
3175 .inferred_alloc_mut,
3176 => unreachable,
1167 switch (child_type.zigTypeTag(mod)) {
1168 .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1169 .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
1170 .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },
1171 else => {},
1172 }
31771173
3178 .generic_poison => unreachable,
1174 switch (strat) {
1175 .eager, .sema => {
1176 if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1177 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1178 .ty = .comptime_int_type,
1179 .storage = .{ .lazy_align = ty.toIntern() },
1180 } })).toValue() },
1181 else => |e| return e,
1182 })) {
1183 return AbiAlignmentAdvanced{ .scalar = 1 };
1184 }
1185 return child_type.abiAlignmentAdvanced(mod, strat);
1186 },
1187 .lazy => switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
1188 .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },
1189 .val => return .{ .val = (try mod.intern(.{ .int = .{
1190 .ty = .comptime_int_type,
1191 .storage = .{ .lazy_align = ty.toIntern() },
1192 } })).toValue() },
1193 },
31791194 }
31801195 }
31811196
31821197 pub fn abiAlignmentAdvancedUnion(
31831198 ty: Type,
3184 target: Target,
1199 mod: *Module,
31851200 strat: AbiAlignmentAdvancedStrat,
31861201 union_obj: *Module.Union,
31871202 have_tag: bool,
......@@ -3195,6 +1210,7 @@ pub const Type = extern union {
31951210 // We'll guess "pointer-aligned", if the union has an
31961211 // underaligned pointer field then some allocations
31971212 // might require explicit alignment.
1213 const target = mod.getTarget();
31981214 return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) };
31991215 }
32001216 _ = try sema.resolveTypeFields(ty);
......@@ -3202,32 +1218,41 @@ pub const Type = extern union {
32021218 if (!union_obj.haveFieldTypes()) switch (strat) {
32031219 .eager => unreachable, // union layout not resolved
32041220 .sema => unreachable, // handled above
3205 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1221 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1222 .ty = .comptime_int_type,
1223 .storage = .{ .lazy_align = ty.toIntern() },
1224 } })).toValue() },
32061225 };
32071226 if (union_obj.fields.count() == 0) {
32081227 if (have_tag) {
3209 return abiAlignmentAdvanced(union_obj.tag_ty, target, strat);
1228 return abiAlignmentAdvanced(union_obj.tag_ty, mod, strat);
32101229 } else {
32111230 return AbiAlignmentAdvanced{ .scalar = @boolToInt(union_obj.layout == .Extern) };
32121231 }
32131232 }
32141233
32151234 var max_align: u32 = 0;
3216 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(target);
1235 if (have_tag) max_align = union_obj.tag_ty.abiAlignment(mod);
32171236 for (union_obj.fields.values()) |field| {
3218 if (!(field.ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3219 error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
1237 if (!(field.ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1238 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1239 .ty = .comptime_int_type,
1240 .storage = .{ .lazy_align = ty.toIntern() },
1241 } })).toValue() },
32201242 else => |e| return e,
32211243 })) continue;
32221244
32231245 const field_align = if (field.abi_align != 0)
32241246 field.abi_align
3225 else switch (try field.ty.abiAlignmentAdvanced(target, strat)) {
1247 else switch (try field.ty.abiAlignmentAdvanced(mod, strat)) {
32261248 .scalar => |a| a,
32271249 .val => switch (strat) {
32281250 .eager => unreachable, // struct layout not resolved
32291251 .sema => unreachable, // handled above
3230 .lazy => |arena| return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
1252 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1253 .ty = .comptime_int_type,
1254 .storage = .{ .lazy_align = ty.toIntern() },
1255 } })).toValue() },
32311256 },
32321257 };
32331258 max_align = @max(max_align, field_align);
......@@ -3236,17 +1261,17 @@ pub const Type = extern union {
32361261 }
32371262
32381263 /// May capture a reference to `ty`.
3239 pub fn lazyAbiSize(ty: Type, target: Target, arena: Allocator) !Value {
3240 switch (try ty.abiSizeAdvanced(target, .{ .lazy = arena })) {
1264 pub fn lazyAbiSize(ty: Type, mod: *Module) !Value {
1265 switch (try ty.abiSizeAdvanced(mod, .lazy)) {
32411266 .val => |val| return val,
3242 .scalar => |x| return Value.Tag.int_u64.create(arena, x),
1267 .scalar => |x| return mod.intValue(Type.comptime_int, x),
32431268 }
32441269 }
32451270
32461271 /// Asserts the type has the ABI size already resolved.
32471272 /// Types that return false for hasRuntimeBits() return 0.
3248 pub fn abiSize(ty: Type, target: Target) u64 {
3249 return (abiSizeAdvanced(ty, target, .eager) catch unreachable).scalar;
1273 pub fn abiSize(ty: Type, mod: *Module) u64 {
1274 return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar;
32501275 }
32511276
32521277 const AbiSizeAdvanced = union(enum) {
......@@ -3262,315 +1287,310 @@ pub const Type = extern union {
32621287 /// necessary, possibly returning a CompileError.
32631288 pub fn abiSizeAdvanced(
32641289 ty: Type,
3265 target: Target,
1290 mod: *Module,
32661291 strat: AbiAlignmentAdvancedStrat,
32671292 ) Module.CompileError!AbiSizeAdvanced {
3268 switch (ty.tag()) {
3269 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
3270 .fn_void_no_args => unreachable, // represents machine code; not a pointer
3271 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer
3272 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer
3273 .function => unreachable, // represents machine code; not a pointer
3274 .@"opaque" => unreachable, // no size available
3275 .noreturn => unreachable,
3276 .inferred_alloc_const => unreachable,
3277 .inferred_alloc_mut => unreachable,
3278 .generic_poison => unreachable,
3279 .modifier => unreachable, // missing call to resolveTypeFields
3280 .prefetch_options => unreachable, // missing call to resolveTypeFields
3281 .export_options => unreachable, // missing call to resolveTypeFields
3282 .extern_options => unreachable, // missing call to resolveTypeFields
3283 .type_info => unreachable, // missing call to resolveTypeFields
3284
3285 .anyopaque,
3286 .type,
3287 .comptime_int,
3288 .comptime_float,
3289 .null,
3290 .undefined,
3291 .enum_literal,
3292 .single_const_pointer_to_comptime_int,
3293 .empty_struct_literal,
3294 .empty_struct,
3295 .void,
3296 => return AbiSizeAdvanced{ .scalar = 0 },
3297
3298 .@"struct", .tuple, .anon_struct => switch (ty.containerLayout()) {
3299 .Packed => {
3300 const struct_obj = ty.castTag(.@"struct").?.data;
3301 switch (strat) {
3302 .sema => |sema| try sema.resolveTypeLayout(ty),
3303 .lazy => |arena| {
3304 if (!struct_obj.haveLayout()) {
3305 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
3306 }
3307 },
3308 .eager => {},
3309 }
3310 assert(struct_obj.haveLayout());
3311 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(target) };
1293 const target = mod.getTarget();
1294
1295 switch (ty.toIntern()) {
1296 .empty_struct_type => return AbiSizeAdvanced{ .scalar = 0 },
1297
1298 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1299 .int_type => |int_type| {
1300 if (int_type.bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
1301 return AbiSizeAdvanced{ .scalar = intAbiSize(int_type.bits, target) };
33121302 },
3313 else => {
3314 switch (strat) {
3315 .sema => |sema| try sema.resolveTypeLayout(ty),
3316 .lazy => |arena| {
3317 if (ty.castTag(.@"struct")) |payload| {
3318 const struct_obj = payload.data;
3319 if (!struct_obj.haveLayout()) {
3320 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
3321 }
3322 }
1303 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1304 .Slice => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
1305 else => return .{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1306 },
1307 .anyframe_type => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1308
1309 .array_type => |array_type| {
1310 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
1311 switch (try array_type.child.toType().abiSizeAdvanced(mod, strat)) {
1312 .scalar => |elem_size| return .{ .scalar = len * elem_size },
1313 .val => switch (strat) {
1314 .sema, .eager => unreachable,
1315 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1316 .ty = .comptime_int_type,
1317 .storage = .{ .lazy_size = ty.toIntern() },
1318 } })).toValue() },
33231319 },
3324 .eager => {},
3325 }
3326 const field_count = ty.structFieldCount();
3327 if (field_count == 0) {
3328 return AbiSizeAdvanced{ .scalar = 0 };
33291320 }
3330 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, target) };
33311321 },
3332 },
3333
3334 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
3335 var buffer: Payload.Bits = undefined;
3336 const int_tag_ty = ty.intTagType(&buffer);
3337 return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(target) };
3338 },
3339 .@"union" => {
3340 const union_obj = ty.castTag(.@"union").?.data;
3341 return abiSizeAdvancedUnion(ty, target, strat, union_obj, false);
3342 },
3343 .union_safety_tagged, .union_tagged => {
3344 const union_obj = ty.cast(Payload.Union).?.data;
3345 return abiSizeAdvancedUnion(ty, target, strat, union_obj, true);
3346 },
3347
3348 .u1,
3349 .u8,
3350 .i8,
3351 .bool,
3352 .atomic_order,
3353 .atomic_rmw_op,
3354 .calling_convention,
3355 .address_space,
3356 .float_mode,
3357 .reduce_op,
3358 => return AbiSizeAdvanced{ .scalar = 1 },
3359
3360 .array_u8 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8).?.data },
3361 .array_u8_sentinel_0 => return AbiSizeAdvanced{ .scalar = ty.castTag(.array_u8_sentinel_0).?.data + 1 },
3362 .array => {
3363 const payload = ty.castTag(.array).?.data;
3364 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
3365 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = payload.len * elem_size },
3366 .val => switch (strat) {
3367 .sema => unreachable,
3368 .eager => unreachable,
3369 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
3370 },
3371 }
3372 },
3373 .array_sentinel => {
3374 const payload = ty.castTag(.array_sentinel).?.data;
3375 switch (try payload.elem_type.abiSizeAdvanced(target, strat)) {
3376 .scalar => |elem_size| return AbiSizeAdvanced{ .scalar = (payload.len + 1) * elem_size },
3377 .val => switch (strat) {
3378 .sema => unreachable,
3379 .eager => unreachable,
3380 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
3381 },
3382 }
3383 },
3384
3385 .vector => {
3386 const payload = ty.castTag(.vector).?.data;
3387 const opt_sema = switch (strat) {
3388 .sema => |sema| sema,
3389 .eager => null,
3390 .lazy => |arena| return AbiSizeAdvanced{
3391 .val = try Value.Tag.lazy_size.create(arena, ty),
3392 },
3393 };
3394 const elem_bits = try payload.elem_type.bitSizeAdvanced(target, opt_sema);
3395 const total_bits = elem_bits * payload.len;
3396 const total_bytes = (total_bits + 7) / 8;
3397 const alignment = switch (try ty.abiAlignmentAdvanced(target, strat)) {
3398 .scalar => |x| x,
3399 .val => return AbiSizeAdvanced{
3400 .val = try Value.Tag.lazy_size.create(strat.lazy, ty),
3401 },
3402 };
3403 const result = std.mem.alignForwardGeneric(u64, total_bytes, alignment);
3404 return AbiSizeAdvanced{ .scalar = result };
3405 },
3406
3407 .isize,
3408 .usize,
3409 .@"anyframe",
3410 .anyframe_T,
3411 .optional_single_const_pointer,
3412 .optional_single_mut_pointer,
3413 .single_const_pointer,
3414 .single_mut_pointer,
3415 .many_const_pointer,
3416 .many_mut_pointer,
3417 .c_const_pointer,
3418 .c_mut_pointer,
3419 .manyptr_u8,
3420 .manyptr_const_u8,
3421 .manyptr_const_u8_sentinel_0,
3422 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3423
3424 .const_slice,
3425 .mut_slice,
3426 .const_slice_u8,
3427 .const_slice_u8_sentinel_0,
3428 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
3429
3430 .pointer => switch (ty.castTag(.pointer).?.data.size) {
3431 .Slice => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) * 2 },
3432 else => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
3433 },
3434
3435 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
3436 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
3437 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
3438 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
3439 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
3440 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
3441 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
3442 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
3443 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
3444 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
3445
3446 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
3447 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
3448 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
3449 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
3450 .f80 => switch (target.c_type_bit_size(.longdouble)) {
3451 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
3452 else => {
3453 var payload: Payload.Bits = .{
3454 .base = .{ .tag = .int_unsigned },
3455 .data = 80,
1322 .vector_type => |vector_type| {
1323 const opt_sema = switch (strat) {
1324 .sema => |sema| sema,
1325 .eager => null,
1326 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1327 .ty = .comptime_int_type,
1328 .storage = .{ .lazy_size = ty.toIntern() },
1329 } })).toValue() },
1330 };
1331 const elem_bits_u64 = try vector_type.child.toType().bitSizeAdvanced(mod, opt_sema);
1332 const elem_bits = @intCast(u32, elem_bits_u64);
1333 const total_bits = elem_bits * vector_type.len;
1334 const total_bytes = (total_bits + 7) / 8;
1335 const alignment = switch (try ty.abiAlignmentAdvanced(mod, strat)) {
1336 .scalar => |x| x,
1337 .val => return .{ .val = (try mod.intern(.{ .int = .{
1338 .ty = .comptime_int_type,
1339 .storage = .{ .lazy_size = ty.toIntern() },
1340 } })).toValue() },
34561341 };
3457 const u80_ty = initPayload(&payload.base);
3458 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, target) };
1342 const result = std.mem.alignForwardGeneric(u32, total_bytes, alignment);
1343 return AbiSizeAdvanced{ .scalar = result };
34591344 },
3460 },
3461
3462 // TODO revisit this when we have the concept of the error tag type
3463 .anyerror_void_error_union,
3464 .anyerror,
3465 .error_set_inferred,
3466 .error_set,
3467 .error_set_merged,
3468 .error_set_single,
3469 => return AbiSizeAdvanced{ .scalar = 2 },
3470
3471 .i16, .u16 => return AbiSizeAdvanced{ .scalar = intAbiSize(16, target) },
3472 .u29 => return AbiSizeAdvanced{ .scalar = intAbiSize(29, target) },
3473 .i32, .u32 => return AbiSizeAdvanced{ .scalar = intAbiSize(32, target) },
3474 .i64, .u64 => return AbiSizeAdvanced{ .scalar = intAbiSize(64, target) },
3475 .u128, .i128 => return AbiSizeAdvanced{ .scalar = intAbiSize(128, target) },
3476 .int_signed, .int_unsigned => {
3477 const bits: u16 = ty.cast(Payload.Bits).?.data;
3478 if (bits == 0) return AbiSizeAdvanced{ .scalar = 0 };
3479 return AbiSizeAdvanced{ .scalar = intAbiSize(bits, target) };
3480 },
34811345
3482 .optional => {
3483 var buf: Payload.ElemType = undefined;
3484 const child_type = ty.optionalChild(&buf);
3485
3486 if (child_type.isNoReturn()) {
3487 return AbiSizeAdvanced{ .scalar = 0 };
3488 }
3489
3490 if (!(child_type.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3491 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },
3492 else => |e| return e,
3493 })) return AbiSizeAdvanced{ .scalar = 1 };
3494
3495 if (ty.optionalReprIsPayload()) {
3496 return abiSizeAdvanced(child_type, target, strat);
3497 }
1346 .opt_type => return ty.abiSizeAdvancedOptional(mod, strat),
1347
1348 // TODO revisit this when we have the concept of the error tag type
1349 .error_set_type, .inferred_error_set_type => return AbiSizeAdvanced{ .scalar = 2 },
1350
1351 .error_union_type => |error_union_type| {
1352 const payload_ty = error_union_type.payload_type.toType();
1353 // This code needs to be kept in sync with the equivalent switch prong
1354 // in abiAlignmentAdvanced.
1355 const code_size = abiSize(Type.anyerror, mod);
1356 if (!(payload_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1357 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1358 .ty = .comptime_int_type,
1359 .storage = .{ .lazy_size = ty.toIntern() },
1360 } })).toValue() },
1361 else => |e| return e,
1362 })) {
1363 // Same as anyerror.
1364 return AbiSizeAdvanced{ .scalar = code_size };
1365 }
1366 const code_align = abiAlignment(Type.anyerror, mod);
1367 const payload_align = abiAlignment(payload_ty, mod);
1368 const payload_size = switch (try payload_ty.abiSizeAdvanced(mod, strat)) {
1369 .scalar => |elem_size| elem_size,
1370 .val => switch (strat) {
1371 .sema => unreachable,
1372 .eager => unreachable,
1373 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1374 .ty = .comptime_int_type,
1375 .storage = .{ .lazy_size = ty.toIntern() },
1376 } })).toValue() },
1377 },
1378 };
34981379
3499 const payload_size = switch (try child_type.abiSizeAdvanced(target, strat)) {
3500 .scalar => |elem_size| elem_size,
3501 .val => switch (strat) {
3502 .sema => unreachable,
3503 .eager => unreachable,
3504 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
1380 var size: u64 = 0;
1381 if (code_align > payload_align) {
1382 size += code_size;
1383 size = std.mem.alignForwardGeneric(u64, size, payload_align);
1384 size += payload_size;
1385 size = std.mem.alignForwardGeneric(u64, size, code_align);
1386 } else {
1387 size += payload_size;
1388 size = std.mem.alignForwardGeneric(u64, size, code_align);
1389 size += code_size;
1390 size = std.mem.alignForwardGeneric(u64, size, payload_align);
1391 }
1392 return AbiSizeAdvanced{ .scalar = size };
1393 },
1394 .func_type => unreachable, // represents machine code; not a pointer
1395 .simple_type => |t| switch (t) {
1396 .bool,
1397 .atomic_order,
1398 .atomic_rmw_op,
1399 .calling_convention,
1400 .address_space,
1401 .float_mode,
1402 .reduce_op,
1403 .call_modifier,
1404 => return AbiSizeAdvanced{ .scalar = 1 },
1405
1406 .f16 => return AbiSizeAdvanced{ .scalar = 2 },
1407 .f32 => return AbiSizeAdvanced{ .scalar = 4 },
1408 .f64 => return AbiSizeAdvanced{ .scalar = 8 },
1409 .f128 => return AbiSizeAdvanced{ .scalar = 16 },
1410 .f80 => switch (target.c_type_bit_size(.longdouble)) {
1411 80 => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1412 else => {
1413 const u80_ty: Type = .{ .ip_index = .u80_type };
1414 return AbiSizeAdvanced{ .scalar = abiSize(u80_ty, mod) };
1415 },
35051416 },
3506 };
35071417
3508 // Optional types are represented as a struct with the child type as the first
3509 // field and a boolean as the second. Since the child type's abi alignment is
3510 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
3511 // to the child type's ABI alignment.
3512 return AbiSizeAdvanced{
3513 .scalar = child_type.abiAlignment(target) + payload_size,
3514 };
3515 },
3516
3517 .error_union => {
3518 // This code needs to be kept in sync with the equivalent switch prong
3519 // in abiAlignmentAdvanced.
3520 const data = ty.castTag(.error_union).?.data;
3521 const code_size = abiSize(Type.anyerror, target);
3522 if (!(data.payload.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
3523 error.NeedLazy => return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(strat.lazy, ty) },
3524 else => |e| return e,
3525 })) {
3526 // Same as anyerror.
3527 return AbiSizeAdvanced{ .scalar = code_size };
3528 }
3529 const code_align = abiAlignment(Type.anyerror, target);
3530 const payload_align = abiAlignment(data.payload, target);
3531 const payload_size = switch (try data.payload.abiSizeAdvanced(target, strat)) {
3532 .scalar => |elem_size| elem_size,
3533 .val => switch (strat) {
3534 .sema => unreachable,
3535 .eager => unreachable,
3536 .lazy => |arena| return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) },
1418 .usize,
1419 .isize,
1420 => return AbiSizeAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
1421
1422 .c_char => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.char) },
1423 .c_short => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.short) },
1424 .c_ushort => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ushort) },
1425 .c_int => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.int) },
1426 .c_uint => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.uint) },
1427 .c_long => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.long) },
1428 .c_ulong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulong) },
1429 .c_longlong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longlong) },
1430 .c_ulonglong => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.ulonglong) },
1431 .c_longdouble => return AbiSizeAdvanced{ .scalar = target.c_type_byte_size(.longdouble) },
1432
1433 .anyopaque,
1434 .void,
1435 .type,
1436 .comptime_int,
1437 .comptime_float,
1438 .null,
1439 .undefined,
1440 .enum_literal,
1441 => return AbiSizeAdvanced{ .scalar = 0 },
1442
1443 // TODO revisit this when we have the concept of the error tag type
1444 .anyerror => return AbiSizeAdvanced{ .scalar = 2 },
1445
1446 .prefetch_options => unreachable, // missing call to resolveTypeFields
1447 .export_options => unreachable, // missing call to resolveTypeFields
1448 .extern_options => unreachable, // missing call to resolveTypeFields
1449
1450 .type_info => unreachable,
1451 .noreturn => unreachable,
1452 .generic_poison => unreachable,
1453 },
1454 .struct_type => |struct_type| switch (ty.containerLayout(mod)) {
1455 .Packed => {
1456 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
1457 return AbiSizeAdvanced{ .scalar = 0 };
1458
1459 switch (strat) {
1460 .sema => |sema| try sema.resolveTypeLayout(ty),
1461 .lazy => if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1462 .ty = .comptime_int_type,
1463 .storage = .{ .lazy_size = ty.toIntern() },
1464 } })).toValue() },
1465 .eager => {},
1466 }
1467 assert(struct_obj.haveLayout());
1468 return AbiSizeAdvanced{ .scalar = struct_obj.backing_int_ty.abiSize(mod) };
35371469 },
3538 };
1470 else => {
1471 switch (strat) {
1472 .sema => |sema| try sema.resolveTypeLayout(ty),
1473 .lazy => {
1474 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse
1475 return AbiSizeAdvanced{ .scalar = 0 };
1476 if (!struct_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1477 .ty = .comptime_int_type,
1478 .storage = .{ .lazy_size = ty.toIntern() },
1479 } })).toValue() };
1480 },
1481 .eager => {},
1482 }
1483 const field_count = ty.structFieldCount(mod);
1484 if (field_count == 0) {
1485 return AbiSizeAdvanced{ .scalar = 0 };
1486 }
1487 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
1488 },
1489 },
1490 .anon_struct_type => |tuple| {
1491 switch (strat) {
1492 .sema => |sema| try sema.resolveTypeLayout(ty),
1493 .lazy, .eager => {},
1494 }
1495 const field_count = tuple.types.len;
1496 if (field_count == 0) {
1497 return AbiSizeAdvanced{ .scalar = 0 };
1498 }
1499 return AbiSizeAdvanced{ .scalar = ty.structFieldOffset(field_count, mod) };
1500 },
35391501
3540 var size: u64 = 0;
3541 if (code_align > payload_align) {
3542 size += code_size;
3543 size = std.mem.alignForwardGeneric(u64, size, payload_align);
3544 size += payload_size;
3545 size = std.mem.alignForwardGeneric(u64, size, code_align);
3546 } else {
3547 size += payload_size;
3548 size = std.mem.alignForwardGeneric(u64, size, code_align);
3549 size += code_size;
3550 size = std.mem.alignForwardGeneric(u64, size, payload_align);
3551 }
3552 return AbiSizeAdvanced{ .scalar = size };
1502 .union_type => |union_type| {
1503 const union_obj = mod.unionPtr(union_type.index);
1504 return abiSizeAdvancedUnion(ty, mod, strat, union_obj, union_type.hasTag());
1505 },
1506 .opaque_type => unreachable, // no size available
1507 .enum_type => |enum_type| return AbiSizeAdvanced{ .scalar = enum_type.tag_ty.toType().abiSize(mod) },
1508
1509 // values, not types
1510 .undef,
1511 .runtime_value,
1512 .simple_value,
1513 .variable,
1514 .extern_func,
1515 .func,
1516 .int,
1517 .err,
1518 .error_union,
1519 .enum_literal,
1520 .enum_tag,
1521 .empty_enum_value,
1522 .float,
1523 .ptr,
1524 .opt,
1525 .aggregate,
1526 .un,
1527 // memoization, not types
1528 .memoized_call,
1529 => unreachable,
35531530 },
35541531 }
35551532 }
35561533
35571534 pub fn abiSizeAdvancedUnion(
35581535 ty: Type,
3559 target: Target,
1536 mod: *Module,
35601537 strat: AbiAlignmentAdvancedStrat,
35611538 union_obj: *Module.Union,
35621539 have_tag: bool,
35631540 ) Module.CompileError!AbiSizeAdvanced {
35641541 switch (strat) {
35651542 .sema => |sema| try sema.resolveTypeLayout(ty),
3566 .lazy => |arena| {
3567 if (!union_obj.haveLayout()) {
3568 return AbiSizeAdvanced{ .val = try Value.Tag.lazy_size.create(arena, ty) };
3569 }
3570 },
1543 .lazy => if (!union_obj.haveLayout()) return .{ .val = (try mod.intern(.{ .int = .{
1544 .ty = .comptime_int_type,
1545 .storage = .{ .lazy_size = ty.toIntern() },
1546 } })).toValue() },
35711547 .eager => {},
35721548 }
3573 return AbiSizeAdvanced{ .scalar = union_obj.abiSize(target, have_tag) };
1549 return AbiSizeAdvanced{ .scalar = union_obj.abiSize(mod, have_tag) };
1550 }
1551
1552 fn abiSizeAdvancedOptional(
1553 ty: Type,
1554 mod: *Module,
1555 strat: AbiAlignmentAdvancedStrat,
1556 ) Module.CompileError!AbiSizeAdvanced {
1557 const child_ty = ty.optionalChild(mod);
1558
1559 if (child_ty.isNoReturn(mod)) {
1560 return AbiSizeAdvanced{ .scalar = 0 };
1561 }
1562
1563 if (!(child_ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
1564 error.NeedLazy => return .{ .val = (try mod.intern(.{ .int = .{
1565 .ty = .comptime_int_type,
1566 .storage = .{ .lazy_size = ty.toIntern() },
1567 } })).toValue() },
1568 else => |e| return e,
1569 })) return AbiSizeAdvanced{ .scalar = 1 };
1570
1571 if (ty.optionalReprIsPayload(mod)) {
1572 return abiSizeAdvanced(child_ty, mod, strat);
1573 }
1574
1575 const payload_size = switch (try child_ty.abiSizeAdvanced(mod, strat)) {
1576 .scalar => |elem_size| elem_size,
1577 .val => switch (strat) {
1578 .sema => unreachable,
1579 .eager => unreachable,
1580 .lazy => return .{ .val = (try mod.intern(.{ .int = .{
1581 .ty = .comptime_int_type,
1582 .storage = .{ .lazy_size = ty.toIntern() },
1583 } })).toValue() },
1584 },
1585 };
1586
1587 // Optional types are represented as a struct with the child type as the first
1588 // field and a boolean as the second. Since the child type's abi alignment is
1589 // guaranteed to be >= that of bool's (1 byte) the added size is exactly equal
1590 // to the child type's ABI alignment.
1591 return AbiSizeAdvanced{
1592 .scalar = child_ty.abiAlignment(mod) + payload_size,
1593 };
35741594 }
35751595
35761596 fn intAbiSize(bits: u16, target: Target) u64 {
......@@ -3585,8 +1605,8 @@ pub const Type = extern union {
35851605 );
35861606 }
35871607
3588 pub fn bitSize(ty: Type, target: Target) u64 {
3589 return bitSizeAdvanced(ty, target, null) catch unreachable;
1608 pub fn bitSize(ty: Type, mod: *Module) u64 {
1609 return bitSizeAdvanced(ty, mod, null) catch unreachable;
35901610 }
35911611
35921612 /// If you pass `opt_sema`, any recursive type resolutions will happen if
......@@ -3594,568 +1614,318 @@ pub const Type = extern union {
35941614 /// the type is fully resolved, and there will be no error, guaranteed.
35951615 pub fn bitSizeAdvanced(
35961616 ty: Type,
3597 target: Target,
1617 mod: *Module,
35981618 opt_sema: ?*Sema,
35991619 ) Module.CompileError!u64 {
1620 const target = mod.getTarget();
1621
36001622 const strat: AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
3601 switch (ty.tag()) {
3602 .fn_noreturn_no_args => unreachable, // represents machine code; not a pointer
3603 .fn_void_no_args => unreachable, // represents machine code; not a pointer
3604 .fn_naked_noreturn_no_args => unreachable, // represents machine code; not a pointer
3605 .fn_ccc_void_no_args => unreachable, // represents machine code; not a pointer
3606 .function => unreachable, // represents machine code; not a pointer
3607 .anyopaque => unreachable,
3608 .type => unreachable,
3609 .comptime_int => unreachable,
3610 .comptime_float => unreachable,
3611 .noreturn => unreachable,
3612 .null => unreachable,
3613 .undefined => unreachable,
3614 .enum_literal => unreachable,
3615 .single_const_pointer_to_comptime_int => unreachable,
3616 .empty_struct => unreachable,
3617 .empty_struct_literal => unreachable,
3618 .inferred_alloc_const => unreachable,
3619 .inferred_alloc_mut => unreachable,
3620 .@"opaque" => unreachable,
3621 .generic_poison => unreachable,
3622
3623 .void => return 0,
3624 .bool, .u1 => return 1,
3625 .u8, .i8 => return 8,
3626 .i16, .u16, .f16 => return 16,
3627 .u29 => return 29,
3628 .i32, .u32, .f32 => return 32,
3629 .i64, .u64, .f64 => return 64,
3630 .f80 => return 80,
3631 .u128, .i128, .f128 => return 128,
3632
3633 .@"struct" => {
3634 const struct_obj = ty.castTag(.@"struct").?.data;
1623
1624 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1625 .int_type => |int_type| return int_type.bits,
1626 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1627 .Slice => return target.ptrBitWidth() * 2,
1628 else => return target.ptrBitWidth(),
1629 },
1630 .anyframe_type => return target.ptrBitWidth(),
1631
1632 .array_type => |array_type| {
1633 const len = array_type.len + @boolToInt(array_type.sentinel != .none);
1634 if (len == 0) return 0;
1635 const elem_ty = array_type.child.toType();
1636 const elem_size = std.math.max(elem_ty.abiAlignment(mod), elem_ty.abiSize(mod));
1637 if (elem_size == 0) return 0;
1638 const elem_bit_size = try bitSizeAdvanced(elem_ty, mod, opt_sema);
1639 return (len - 1) * 8 * elem_size + elem_bit_size;
1640 },
1641 .vector_type => |vector_type| {
1642 const child_ty = vector_type.child.toType();
1643 const elem_bit_size = try bitSizeAdvanced(child_ty, mod, opt_sema);
1644 return elem_bit_size * vector_type.len;
1645 },
1646 .opt_type => {
1647 // Optionals and error unions are not packed so their bitsize
1648 // includes padding bits.
1649 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
1650 },
1651
1652 // TODO revisit this when we have the concept of the error tag type
1653 .error_set_type, .inferred_error_set_type => return 16,
1654
1655 .error_union_type => {
1656 // Optionals and error unions are not packed so their bitsize
1657 // includes padding bits.
1658 return (try abiSizeAdvanced(ty, mod, strat)).scalar * 8;
1659 },
1660 .func_type => unreachable, // represents machine code; not a pointer
1661 .simple_type => |t| switch (t) {
1662 .f16 => return 16,
1663 .f32 => return 32,
1664 .f64 => return 64,
1665 .f80 => return 80,
1666 .f128 => return 128,
1667
1668 .usize,
1669 .isize,
1670 => return target.ptrBitWidth(),
1671
1672 .c_char => return target.c_type_bit_size(.char),
1673 .c_short => return target.c_type_bit_size(.short),
1674 .c_ushort => return target.c_type_bit_size(.ushort),
1675 .c_int => return target.c_type_bit_size(.int),
1676 .c_uint => return target.c_type_bit_size(.uint),
1677 .c_long => return target.c_type_bit_size(.long),
1678 .c_ulong => return target.c_type_bit_size(.ulong),
1679 .c_longlong => return target.c_type_bit_size(.longlong),
1680 .c_ulonglong => return target.c_type_bit_size(.ulonglong),
1681 .c_longdouble => return target.c_type_bit_size(.longdouble),
1682
1683 .bool => return 1,
1684 .void => return 0,
1685
1686 // TODO revisit this when we have the concept of the error tag type
1687 .anyerror => return 16,
1688
1689 .anyopaque => unreachable,
1690 .type => unreachable,
1691 .comptime_int => unreachable,
1692 .comptime_float => unreachable,
1693 .noreturn => unreachable,
1694 .null => unreachable,
1695 .undefined => unreachable,
1696 .enum_literal => unreachable,
1697 .generic_poison => unreachable,
1698
1699 .atomic_order => unreachable, // missing call to resolveTypeFields
1700 .atomic_rmw_op => unreachable, // missing call to resolveTypeFields
1701 .calling_convention => unreachable, // missing call to resolveTypeFields
1702 .address_space => unreachable, // missing call to resolveTypeFields
1703 .float_mode => unreachable, // missing call to resolveTypeFields
1704 .reduce_op => unreachable, // missing call to resolveTypeFields
1705 .call_modifier => unreachable, // missing call to resolveTypeFields
1706 .prefetch_options => unreachable, // missing call to resolveTypeFields
1707 .export_options => unreachable, // missing call to resolveTypeFields
1708 .extern_options => unreachable, // missing call to resolveTypeFields
1709 .type_info => unreachable, // missing call to resolveTypeFields
1710 },
1711 .struct_type => |struct_type| {
1712 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
36351713 if (struct_obj.layout != .Packed) {
3636 return (try ty.abiSizeAdvanced(target, strat)).scalar * 8;
1714 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
36371715 }
36381716 if (opt_sema) |sema| _ = try sema.resolveTypeLayout(ty);
36391717 assert(struct_obj.haveLayout());
3640 return try struct_obj.backing_int_ty.bitSizeAdvanced(target, opt_sema);
1718 return try struct_obj.backing_int_ty.bitSizeAdvanced(mod, opt_sema);
36411719 },
36421720
3643 .tuple, .anon_struct => {
1721 .anon_struct_type => {
36441722 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
3645 if (ty.containerLayout() != .Packed) {
3646 return (try ty.abiSizeAdvanced(target, strat)).scalar * 8;
3647 }
3648 var total: u64 = 0;
3649 for (ty.tupleFields().types) |field_ty| {
3650 total += try bitSizeAdvanced(field_ty, target, opt_sema);
3651 }
3652 return total;
3653 },
3654
3655 .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
3656 var buffer: Payload.Bits = undefined;
3657 const int_tag_ty = ty.intTagType(&buffer);
3658 return try bitSizeAdvanced(int_tag_ty, target, opt_sema);
1723 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
36591724 },
36601725
3661 .@"union", .union_safety_tagged, .union_tagged => {
1726 .union_type => |union_type| {
36621727 if (opt_sema) |sema| _ = try sema.resolveTypeFields(ty);
3663 if (ty.containerLayout() != .Packed) {
3664 return (try ty.abiSizeAdvanced(target, strat)).scalar * 8;
1728 if (ty.containerLayout(mod) != .Packed) {
1729 return (try ty.abiSizeAdvanced(mod, strat)).scalar * 8;
36651730 }
3666 const union_obj = ty.cast(Payload.Union).?.data;
1731 const union_obj = mod.unionPtr(union_type.index);
36671732 assert(union_obj.haveFieldTypes());
36681733
36691734 var size: u64 = 0;
36701735 for (union_obj.fields.values()) |field| {
3671 size = @max(size, try bitSizeAdvanced(field.ty, target, opt_sema));
1736 size = @max(size, try bitSizeAdvanced(field.ty, mod, opt_sema));
36721737 }
36731738 return size;
36741739 },
3675
3676 .vector => {
3677 const payload = ty.castTag(.vector).?.data;
3678 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema);
3679 return elem_bit_size * payload.len;
3680 },
3681 .array_u8 => return 8 * ty.castTag(.array_u8).?.data,
3682 .array_u8_sentinel_0 => return 8 * (ty.castTag(.array_u8_sentinel_0).?.data + 1),
3683 .array => {
3684 const payload = ty.castTag(.array).?.data;
3685 const elem_size = std.math.max(payload.elem_type.abiAlignment(target), payload.elem_type.abiSize(target));
3686 if (elem_size == 0 or payload.len == 0)
3687 return @as(u64, 0);
3688 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema);
3689 return (payload.len - 1) * 8 * elem_size + elem_bit_size;
3690 },
3691 .array_sentinel => {
3692 const payload = ty.castTag(.array_sentinel).?.data;
3693 const elem_size = std.math.max(
3694 payload.elem_type.abiAlignment(target),
3695 payload.elem_type.abiSize(target),
3696 );
3697 const elem_bit_size = try bitSizeAdvanced(payload.elem_type, target, opt_sema);
3698 return payload.len * 8 * elem_size + elem_bit_size;
3699 },
3700
3701 .isize,
3702 .usize,
3703 .@"anyframe",
3704 .anyframe_T,
3705 => return target.ptrBitWidth(),
3706
3707 .const_slice,
3708 .mut_slice,
3709 => return target.ptrBitWidth() * 2,
3710
3711 .const_slice_u8,
3712 .const_slice_u8_sentinel_0,
3713 => return target.ptrBitWidth() * 2,
3714
3715 .optional_single_const_pointer,
3716 .optional_single_mut_pointer,
3717 => {
3718 return target.ptrBitWidth();
3719 },
3720
3721 .single_const_pointer,
3722 .single_mut_pointer,
3723 .many_const_pointer,
3724 .many_mut_pointer,
3725 .c_const_pointer,
3726 .c_mut_pointer,
3727 => {
3728 return target.ptrBitWidth();
3729 },
3730
3731 .pointer => switch (ty.castTag(.pointer).?.data.size) {
3732 .Slice => return target.ptrBitWidth() * 2,
3733 else => return target.ptrBitWidth(),
3734 },
3735
3736 .manyptr_u8,
3737 .manyptr_const_u8,
3738 .manyptr_const_u8_sentinel_0,
3739 => return target.ptrBitWidth(),
3740
3741 .c_char => return target.c_type_bit_size(.char),
3742 .c_short => return target.c_type_bit_size(.short),
3743 .c_ushort => return target.c_type_bit_size(.ushort),
3744 .c_int => return target.c_type_bit_size(.int),
3745 .c_uint => return target.c_type_bit_size(.uint),
3746 .c_long => return target.c_type_bit_size(.long),
3747 .c_ulong => return target.c_type_bit_size(.ulong),
3748 .c_longlong => return target.c_type_bit_size(.longlong),
3749 .c_ulonglong => return target.c_type_bit_size(.ulonglong),
3750 .c_longdouble => return target.c_type_bit_size(.longdouble),
3751
3752 .error_set,
3753 .error_set_single,
3754 .anyerror_void_error_union,
3755 .anyerror,
3756 .error_set_inferred,
3757 .error_set_merged,
3758 => return 16, // TODO revisit this when we have the concept of the error tag type
3759
3760 .int_signed, .int_unsigned => return ty.cast(Payload.Bits).?.data,
3761
3762 .optional, .error_union => {
3763 // Optionals and error unions are not packed so their bitsize
3764 // includes padding bits.
3765 return (try abiSizeAdvanced(ty, target, strat)).scalar * 8;
3766 },
3767
3768 .atomic_order,
3769 .atomic_rmw_op,
3770 .calling_convention,
3771 .address_space,
3772 .float_mode,
3773 .reduce_op,
3774 .modifier,
3775 .prefetch_options,
3776 .export_options,
3777 .extern_options,
3778 .type_info,
3779 => @panic("TODO at some point we gotta resolve builtin types"),
1740 .opaque_type => unreachable,
1741 .enum_type => |enum_type| return bitSizeAdvanced(enum_type.tag_ty.toType(), mod, opt_sema),
1742
1743 // values, not types
1744 .undef,
1745 .runtime_value,
1746 .simple_value,
1747 .variable,
1748 .extern_func,
1749 .func,
1750 .int,
1751 .err,
1752 .error_union,
1753 .enum_literal,
1754 .enum_tag,
1755 .empty_enum_value,
1756 .float,
1757 .ptr,
1758 .opt,
1759 .aggregate,
1760 .un,
1761 // memoization, not types
1762 .memoized_call,
1763 => unreachable,
37801764 }
37811765 }
37821766
37831767 /// Returns true if the type's layout is already resolved and it is safe
37841768 /// to use `abiSize`, `abiAlignment` and `bitSize` on it.
3785 pub fn layoutIsResolved(ty: Type) bool {
3786 switch (ty.zigTypeTag()) {
1769 pub fn layoutIsResolved(ty: Type, mod: *Module) bool {
1770 switch (ty.zigTypeTag(mod)) {
37871771 .Struct => {
3788 if (ty.castTag(.@"struct")) |struct_ty| {
3789 return struct_ty.data.haveLayout();
1772 if (mod.typeToStruct(ty)) |struct_obj| {
1773 return struct_obj.haveLayout();
37901774 }
37911775 return true;
37921776 },
37931777 .Union => {
3794 if (ty.cast(Payload.Union)) |union_ty| {
3795 return union_ty.data.haveLayout();
1778 if (mod.typeToUnion(ty)) |union_obj| {
1779 return union_obj.haveLayout();
37961780 }
37971781 return true;
37981782 },
37991783 .Array => {
3800 if (ty.arrayLenIncludingSentinel() == 0) return true;
3801 return ty.childType().layoutIsResolved();
1784 if (ty.arrayLenIncludingSentinel(mod) == 0) return true;
1785 return ty.childType(mod).layoutIsResolved(mod);
38021786 },
38031787 .Optional => {
3804 var buf: Type.Payload.ElemType = undefined;
3805 const payload_ty = ty.optionalChild(&buf);
3806 return payload_ty.layoutIsResolved();
1788 const payload_ty = ty.optionalChild(mod);
1789 return payload_ty.layoutIsResolved(mod);
38071790 },
38081791 .ErrorUnion => {
3809 const payload_ty = ty.errorUnionPayload();
3810 return payload_ty.layoutIsResolved();
1792 const payload_ty = ty.errorUnionPayload(mod);
1793 return payload_ty.layoutIsResolved(mod);
38111794 },
38121795 else => return true,
38131796 }
38141797 }
38151798
3816 pub fn isSinglePointer(self: Type) bool {
3817 return switch (self.tag()) {
3818 .single_const_pointer,
3819 .single_mut_pointer,
3820 .single_const_pointer_to_comptime_int,
3821 .inferred_alloc_const,
3822 .inferred_alloc_mut,
3823 => true,
3824
3825 .pointer => self.castTag(.pointer).?.data.size == .One,
3826
1799 pub fn isSinglePointer(ty: Type, mod: *const Module) bool {
1800 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1801 .ptr_type => |ptr_info| ptr_info.flags.size == .One,
38271802 else => false,
38281803 };
38291804 }
38301805
38311806 /// Asserts `ty` is a pointer.
3832 pub fn ptrSize(ty: Type) std.builtin.Type.Pointer.Size {
3833 return ptrSizeOrNull(ty).?;
1807 pub fn ptrSize(ty: Type, mod: *const Module) std.builtin.Type.Pointer.Size {
1808 return ptrSizeOrNull(ty, mod).?;
38341809 }
38351810
38361811 /// Returns `null` if `ty` is not a pointer.
3837 pub fn ptrSizeOrNull(ty: Type) ?std.builtin.Type.Pointer.Size {
3838 return switch (ty.tag()) {
3839 .const_slice,
3840 .mut_slice,
3841 .const_slice_u8,
3842 .const_slice_u8_sentinel_0,
3843 => .Slice,
3844
3845 .many_const_pointer,
3846 .many_mut_pointer,
3847 .manyptr_u8,
3848 .manyptr_const_u8,
3849 .manyptr_const_u8_sentinel_0,
3850 => .Many,
3851
3852 .c_const_pointer,
3853 .c_mut_pointer,
3854 => .C,
3855
3856 .single_const_pointer,
3857 .single_mut_pointer,
3858 .single_const_pointer_to_comptime_int,
3859 .inferred_alloc_const,
3860 .inferred_alloc_mut,
3861 => .One,
3862
3863 .pointer => ty.castTag(.pointer).?.data.size,
3864
1812 pub fn ptrSizeOrNull(ty: Type, mod: *const Module) ?std.builtin.Type.Pointer.Size {
1813 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1814 .ptr_type => |ptr_info| ptr_info.flags.size,
38651815 else => null,
38661816 };
38671817 }
38681818
3869 pub fn isSlice(self: Type) bool {
3870 return switch (self.tag()) {
3871 .const_slice,
3872 .mut_slice,
3873 .const_slice_u8,
3874 .const_slice_u8_sentinel_0,
3875 => true,
3876
3877 .pointer => self.castTag(.pointer).?.data.size == .Slice,
3878
1819 pub fn isSlice(ty: Type, mod: *const Module) bool {
1820 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1821 .ptr_type => |ptr_type| ptr_type.flags.size == .Slice,
38791822 else => false,
38801823 };
38811824 }
38821825
3883 pub const SlicePtrFieldTypeBuffer = union {
3884 elem_type: Payload.ElemType,
3885 pointer: Payload.Pointer,
3886 };
3887
3888 pub fn slicePtrFieldType(self: Type, buffer: *SlicePtrFieldTypeBuffer) Type {
3889 switch (self.tag()) {
3890 .const_slice_u8 => return Type.initTag(.manyptr_const_u8),
3891 .const_slice_u8_sentinel_0 => return Type.initTag(.manyptr_const_u8_sentinel_0),
3892
3893 .const_slice => {
3894 const elem_type = self.castTag(.const_slice).?.data;
3895 buffer.* = .{
3896 .elem_type = .{
3897 .base = .{ .tag = .many_const_pointer },
3898 .data = elem_type,
3899 },
3900 };
3901 return Type.initPayload(&buffer.elem_type.base);
3902 },
3903 .mut_slice => {
3904 const elem_type = self.castTag(.mut_slice).?.data;
3905 buffer.* = .{
3906 .elem_type = .{
3907 .base = .{ .tag = .many_mut_pointer },
3908 .data = elem_type,
3909 },
3910 };
3911 return Type.initPayload(&buffer.elem_type.base);
3912 },
3913
3914 .pointer => {
3915 const payload = self.castTag(.pointer).?.data;
3916 assert(payload.size == .Slice);
3917
3918 if (payload.sentinel != null or
3919 payload.@"align" != 0 or
3920 payload.@"addrspace" != .generic or
3921 payload.bit_offset != 0 or
3922 payload.host_size != 0 or
3923 payload.vector_index != .none or
3924 payload.@"allowzero" or
3925 payload.@"volatile")
3926 {
3927 buffer.* = .{
3928 .pointer = .{
3929 .data = .{
3930 .pointee_type = payload.pointee_type,
3931 .sentinel = payload.sentinel,
3932 .@"align" = payload.@"align",
3933 .@"addrspace" = payload.@"addrspace",
3934 .bit_offset = payload.bit_offset,
3935 .host_size = payload.host_size,
3936 .vector_index = payload.vector_index,
3937 .@"allowzero" = payload.@"allowzero",
3938 .mutable = payload.mutable,
3939 .@"volatile" = payload.@"volatile",
3940 .size = .Many,
3941 },
3942 },
3943 };
3944 return Type.initPayload(&buffer.pointer.base);
3945 } else if (payload.mutable) {
3946 buffer.* = .{
3947 .elem_type = .{
3948 .base = .{ .tag = .many_mut_pointer },
3949 .data = payload.pointee_type,
3950 },
3951 };
3952 return Type.initPayload(&buffer.elem_type.base);
3953 } else {
3954 buffer.* = .{
3955 .elem_type = .{
3956 .base = .{ .tag = .many_const_pointer },
3957 .data = payload.pointee_type,
3958 },
3959 };
3960 return Type.initPayload(&buffer.elem_type.base);
3961 }
3962 },
3963
3964 else => unreachable,
3965 }
1826 pub fn slicePtrFieldType(ty: Type, mod: *const Module) Type {
1827 return mod.intern_pool.slicePtrType(ty.toIntern()).toType();
39661828 }
39671829
3968 pub fn isConstPtr(self: Type) bool {
3969 return switch (self.tag()) {
3970 .single_const_pointer,
3971 .many_const_pointer,
3972 .c_const_pointer,
3973 .single_const_pointer_to_comptime_int,
3974 .const_slice_u8,
3975 .const_slice_u8_sentinel_0,
3976 .const_slice,
3977 .manyptr_const_u8,
3978 .manyptr_const_u8_sentinel_0,
3979 => true,
3980
3981 .pointer => !self.castTag(.pointer).?.data.mutable,
3982
1830 pub fn isConstPtr(ty: Type, mod: *const Module) bool {
1831 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1832 .ptr_type => |ptr_type| ptr_type.flags.is_const,
39831833 else => false,
39841834 };
39851835 }
39861836
3987 pub fn isVolatilePtr(self: Type) bool {
3988 return switch (self.tag()) {
3989 .pointer => {
3990 const payload = self.castTag(.pointer).?.data;
3991 return payload.@"volatile";
3992 },
1837 pub fn isVolatilePtr(ty: Type, mod: *const Module) bool {
1838 return isVolatilePtrIp(ty, &mod.intern_pool);
1839 }
1840
1841 pub fn isVolatilePtrIp(ty: Type, ip: *const InternPool) bool {
1842 return switch (ip.indexToKey(ty.toIntern())) {
1843 .ptr_type => |ptr_type| ptr_type.flags.is_volatile,
39931844 else => false,
39941845 };
39951846 }
39961847
3997 pub fn isAllowzeroPtr(self: Type) bool {
3998 return switch (self.tag()) {
3999 .pointer => {
4000 const payload = self.castTag(.pointer).?.data;
4001 return payload.@"allowzero";
4002 },
4003 else => return self.zigTypeTag() == .Optional,
1848 pub fn isAllowzeroPtr(ty: Type, mod: *const Module) bool {
1849 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1850 .ptr_type => |ptr_type| ptr_type.flags.is_allowzero,
1851 .opt_type => true,
1852 else => false,
40041853 };
40051854 }
40061855
4007 pub fn isCPtr(self: Type) bool {
4008 return switch (self.tag()) {
4009 .c_const_pointer,
4010 .c_mut_pointer,
4011 => return true,
4012
4013 .pointer => self.castTag(.pointer).?.data.size == .C,
4014
4015 else => return false,
1856 pub fn isCPtr(ty: Type, mod: *const Module) bool {
1857 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1858 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1859 else => false,
40161860 };
40171861 }
40181862
4019 pub fn isPtrAtRuntime(self: Type) bool {
4020 switch (self.tag()) {
4021 .c_const_pointer,
4022 .c_mut_pointer,
4023 .many_const_pointer,
4024 .many_mut_pointer,
4025 .manyptr_const_u8,
4026 .manyptr_const_u8_sentinel_0,
4027 .manyptr_u8,
4028 .optional_single_const_pointer,
4029 .optional_single_mut_pointer,
4030 .single_const_pointer,
4031 .single_const_pointer_to_comptime_int,
4032 .single_mut_pointer,
4033 => return true,
4034
4035 .pointer => switch (self.castTag(.pointer).?.data.size) {
4036 .Slice => return false,
4037 .One, .Many, .C => return true,
1863 pub fn isPtrAtRuntime(ty: Type, mod: *const Module) bool {
1864 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1865 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1866 .Slice => false,
1867 .One, .Many, .C => true,
40381868 },
4039
4040 .optional => {
4041 var buf: Payload.ElemType = undefined;
4042 const child_type = self.optionalChild(&buf);
4043 if (child_type.zigTypeTag() != .Pointer) return false;
4044 const info = child_type.ptrInfo().data;
4045 switch (info.size) {
4046 .Slice, .C => return false,
4047 .Many, .One => return !info.@"allowzero",
4048 }
1869 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1870 .ptr_type => |p| switch (p.flags.size) {
1871 .Slice, .C => false,
1872 .Many, .One => !p.flags.is_allowzero,
1873 },
1874 else => false,
40491875 },
4050
4051 else => return false,
4052 }
1876 else => false,
1877 };
40531878 }
40541879
40551880 /// For pointer-like optionals, returns true, otherwise returns the allowzero property
40561881 /// of pointers.
4057 pub fn ptrAllowsZero(ty: Type) bool {
4058 if (ty.isPtrLikeOptional()) {
1882 pub fn ptrAllowsZero(ty: Type, mod: *const Module) bool {
1883 if (ty.isPtrLikeOptional(mod)) {
40591884 return true;
40601885 }
4061 return ty.ptrInfo().data.@"allowzero";
1886 return ty.ptrInfo(mod).@"allowzero";
40621887 }
40631888
40641889 /// See also `isPtrLikeOptional`.
4065 pub fn optionalReprIsPayload(ty: Type) bool {
4066 switch (ty.tag()) {
4067 .optional_single_const_pointer,
4068 .optional_single_mut_pointer,
4069 .c_const_pointer,
4070 .c_mut_pointer,
4071 => return true,
4072
4073 .optional => {
4074 const child_ty = ty.castTag(.optional).?.data;
4075 switch (child_ty.zigTypeTag()) {
4076 .Pointer => {
4077 const info = child_ty.ptrInfo().data;
4078 switch (info.size) {
4079 .C => return false,
4080 .Slice, .Many, .One => return !info.@"allowzero",
4081 }
4082 },
4083 .ErrorSet => return true,
4084 else => return false,
4085 }
4086 },
4087
4088 .pointer => return ty.castTag(.pointer).?.data.size == .C,
4089
4090 else => return false,
4091 }
1890 pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
1891 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1892 .opt_type => |child_type| child_type == .anyerror_type or switch (mod.intern_pool.indexToKey(child_type)) {
1893 .ptr_type => |ptr_type| ptr_type.flags.size != .C and !ptr_type.flags.is_allowzero,
1894 .error_set_type => true,
1895 else => false,
1896 },
1897 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1898 else => false,
1899 };
40921900 }
40931901
40941902 /// Returns true if the type is optional and would be lowered to a single pointer
40951903 /// address value, using 0 for null. Note that this returns true for C pointers.
4096 pub fn isPtrLikeOptional(self: Type) bool {
4097 switch (self.tag()) {
4098 .optional_single_const_pointer,
4099 .optional_single_mut_pointer,
4100 .c_const_pointer,
4101 .c_mut_pointer,
4102 => return true,
4103
4104 .optional => {
4105 const child_ty = self.castTag(.optional).?.data;
4106 if (child_ty.zigTypeTag() != .Pointer) return false;
4107 const info = child_ty.ptrInfo().data;
4108 switch (info.size) {
4109 .Slice, .C => return false,
4110 .Many, .One => return !info.@"allowzero",
4111 }
1904 /// This function must be kept in sync with `Sema.typePtrOrOptionalPtrTy`.
1905 pub fn isPtrLikeOptional(ty: Type, mod: *const Module) bool {
1906 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1907 .ptr_type => |ptr_type| ptr_type.flags.size == .C,
1908 .opt_type => |child| switch (mod.intern_pool.indexToKey(child)) {
1909 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1910 .Slice, .C => false,
1911 .Many, .One => !ptr_type.flags.is_allowzero,
1912 },
1913 else => false,
41121914 },
4113
4114 .pointer => return self.castTag(.pointer).?.data.size == .C,
4115
4116 else => return false,
4117 }
1915 else => false,
1916 };
41181917 }
41191918
41201919 /// For *[N]T, returns [N]T.
41211920 /// For *T, returns T.
41221921 /// For [*]T, returns T.
4123 pub fn childType(ty: Type) Type {
4124 return switch (ty.tag()) {
4125 .vector => ty.castTag(.vector).?.data.elem_type,
4126 .array => ty.castTag(.array).?.data.elem_type,
4127 .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type,
4128 .optional_single_mut_pointer,
4129 .optional_single_const_pointer,
4130 .single_const_pointer,
4131 .single_mut_pointer,
4132 .many_const_pointer,
4133 .many_mut_pointer,
4134 .c_const_pointer,
4135 .c_mut_pointer,
4136 .const_slice,
4137 .mut_slice,
4138 => ty.castPointer().?.data,
4139
4140 .array_u8,
4141 .array_u8_sentinel_0,
4142 .const_slice_u8,
4143 .const_slice_u8_sentinel_0,
4144 .manyptr_u8,
4145 .manyptr_const_u8,
4146 .manyptr_const_u8_sentinel_0,
4147 => Type.u8,
4148
4149 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
4150 .pointer => ty.castTag(.pointer).?.data.pointee_type,
4151
4152 else => unreachable,
4153 };
1922 pub fn childType(ty: Type, mod: *const Module) Type {
1923 return childTypeIp(ty, &mod.intern_pool);
41541924 }
41551925
4156 /// Asserts the type is a pointer or array type.
4157 /// TODO this is deprecated in favor of `childType`.
4158 pub const elemType = childType;
1926 pub fn childTypeIp(ty: Type, ip: *const InternPool) Type {
1927 return ip.childType(ty.toIntern()).toType();
1928 }
41591929
41601930 /// For *[N]T, returns T.
41611931 /// For ?*T, returns T.
......@@ -4166,283 +1936,178 @@ pub const Type = extern union {
41661936 /// For [N]T, returns T.
41671937 /// For []T, returns T.
41681938 /// For anyframe->T, returns T.
4169 pub fn elemType2(ty: Type) Type {
4170 return switch (ty.tag()) {
4171 .vector => ty.castTag(.vector).?.data.elem_type,
4172 .array => ty.castTag(.array).?.data.elem_type,
4173 .array_sentinel => ty.castTag(.array_sentinel).?.data.elem_type,
4174 .many_const_pointer,
4175 .many_mut_pointer,
4176 .c_const_pointer,
4177 .c_mut_pointer,
4178 .const_slice,
4179 .mut_slice,
4180 => ty.castPointer().?.data,
4181
4182 .single_const_pointer,
4183 .single_mut_pointer,
4184 => ty.castPointer().?.data.shallowElemType(),
4185
4186 .array_u8,
4187 .array_u8_sentinel_0,
4188 .const_slice_u8,
4189 .const_slice_u8_sentinel_0,
4190 .manyptr_u8,
4191 .manyptr_const_u8,
4192 .manyptr_const_u8_sentinel_0,
4193 => Type.u8,
4194
4195 .single_const_pointer_to_comptime_int => Type.initTag(.comptime_int),
4196 .pointer => {
4197 const info = ty.castTag(.pointer).?.data;
4198 const child_ty = info.pointee_type;
4199 if (info.size == .One) {
4200 return child_ty.shallowElemType();
4201 } else {
4202 return child_ty;
4203 }
4204 },
4205 .optional => ty.castTag(.optional).?.data.childType(),
4206 .optional_single_mut_pointer => ty.castPointer().?.data,
4207 .optional_single_const_pointer => ty.castPointer().?.data,
4208
4209 .anyframe_T => ty.castTag(.anyframe_T).?.data,
4210 .@"anyframe" => Type.void,
4211
1939 pub fn elemType2(ty: Type, mod: *const Module) Type {
1940 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1941 .ptr_type => |ptr_type| switch (ptr_type.flags.size) {
1942 .One => ptr_type.child.toType().shallowElemType(mod),
1943 .Many, .C, .Slice => ptr_type.child.toType(),
1944 },
1945 .anyframe_type => |child| {
1946 assert(child != .none);
1947 return child.toType();
1948 },
1949 .vector_type => |vector_type| vector_type.child.toType(),
1950 .array_type => |array_type| array_type.child.toType(),
1951 .opt_type => |child| mod.intern_pool.childType(child).toType(),
42121952 else => unreachable,
42131953 };
42141954 }
42151955
4216 fn shallowElemType(child_ty: Type) Type {
4217 return switch (child_ty.zigTypeTag()) {
4218 .Array, .Vector => child_ty.childType(),
1956 fn shallowElemType(child_ty: Type, mod: *const Module) Type {
1957 return switch (child_ty.zigTypeTag(mod)) {
1958 .Array, .Vector => child_ty.childType(mod),
42191959 else => child_ty,
42201960 };
42211961 }
42221962
42231963 /// For vectors, returns the element type. Otherwise returns self.
4224 pub fn scalarType(ty: Type) Type {
4225 return switch (ty.zigTypeTag()) {
4226 .Vector => ty.childType(),
1964 pub fn scalarType(ty: Type, mod: *Module) Type {
1965 return switch (ty.zigTypeTag(mod)) {
1966 .Vector => ty.childType(mod),
42271967 else => ty,
42281968 };
42291969 }
42301970
42311971 /// Asserts that the type is an optional.
4232 /// Resulting `Type` will have inner memory referencing `buf`.
42331972 /// Note that for C pointers this returns the type unmodified.
4234 pub fn optionalChild(ty: Type, buf: *Payload.ElemType) Type {
4235 return switch (ty.tag()) {
4236 .optional => ty.castTag(.optional).?.data,
4237 .optional_single_mut_pointer => {
4238 buf.* = .{
4239 .base = .{ .tag = .single_mut_pointer },
4240 .data = ty.castPointer().?.data,
4241 };
4242 return Type.initPayload(&buf.base);
4243 },
4244 .optional_single_const_pointer => {
4245 buf.* = .{
4246 .base = .{ .tag = .single_const_pointer },
4247 .data = ty.castPointer().?.data,
4248 };
4249 return Type.initPayload(&buf.base);
1973 pub fn optionalChild(ty: Type, mod: *const Module) Type {
1974 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1975 .opt_type => |child| child.toType(),
1976 .ptr_type => |ptr_type| b: {
1977 assert(ptr_type.flags.size == .C);
1978 break :b ty;
42501979 },
4251
4252 .pointer, // here we assume it is a C pointer
4253 .c_const_pointer,
4254 .c_mut_pointer,
4255 => return ty,
4256
42571980 else => unreachable,
42581981 };
42591982 }
42601983
4261 /// Asserts that the type is an optional.
4262 /// Same as `optionalChild` but allocates the buffer if needed.
4263 pub fn optionalChildAlloc(ty: Type, allocator: Allocator) !Type {
4264 switch (ty.tag()) {
4265 .optional => return ty.castTag(.optional).?.data,
4266 .optional_single_mut_pointer => {
4267 return Tag.single_mut_pointer.create(allocator, ty.castPointer().?.data);
4268 },
4269 .optional_single_const_pointer => {
4270 return Tag.single_const_pointer.create(allocator, ty.castPointer().?.data);
4271 },
4272 .pointer, // here we assume it is a C pointer
4273 .c_const_pointer,
4274 .c_mut_pointer,
4275 => return ty,
4276
4277 else => unreachable,
4278 }
4279 }
4280
42811984 /// Returns the tag type of a union, if the type is a union and it has a tag type.
42821985 /// Otherwise, returns `null`.
4283 pub fn unionTagType(ty: Type) ?Type {
4284 return switch (ty.tag()) {
4285 .union_tagged => {
4286 const union_obj = ty.castTag(.union_tagged).?.data;
4287 assert(union_obj.haveFieldTypes());
4288 return union_obj.tag_ty;
1986 pub fn unionTagType(ty: Type, mod: *Module) ?Type {
1987 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1988 .union_type => |union_type| switch (union_type.runtime_tag) {
1989 .tagged => {
1990 const union_obj = mod.unionPtr(union_type.index);
1991 assert(union_obj.haveFieldTypes());
1992 return union_obj.tag_ty;
1993 },
1994 else => null,
42891995 },
4290
4291 .atomic_order,
4292 .atomic_rmw_op,
4293 .calling_convention,
4294 .address_space,
4295 .float_mode,
4296 .reduce_op,
4297 .modifier,
4298 .prefetch_options,
4299 .export_options,
4300 .extern_options,
4301 .type_info,
4302 => unreachable, // needed to call resolveTypeFields first
4303
43041996 else => null,
43051997 };
43061998 }
43071999
43082000 /// Same as `unionTagType` but includes safety tag.
43092001 /// Codegen should use this version.
4310 pub fn unionTagTypeSafety(ty: Type) ?Type {
4311 return switch (ty.tag()) {
4312 .union_safety_tagged, .union_tagged => {
4313 const union_obj = ty.cast(Payload.Union).?.data;
2002 pub fn unionTagTypeSafety(ty: Type, mod: *Module) ?Type {
2003 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2004 .union_type => |union_type| {
2005 if (!union_type.hasTag()) return null;
2006 const union_obj = mod.unionPtr(union_type.index);
43142007 assert(union_obj.haveFieldTypes());
43152008 return union_obj.tag_ty;
43162009 },
4317
4318 .atomic_order,
4319 .atomic_rmw_op,
4320 .calling_convention,
4321 .address_space,
4322 .float_mode,
4323 .reduce_op,
4324 .modifier,
4325 .prefetch_options,
4326 .export_options,
4327 .extern_options,
4328 .type_info,
4329 => unreachable, // needed to call resolveTypeFields first
4330
43312010 else => null,
43322011 };
43332012 }
43342013
43352014 /// Asserts the type is a union; returns the tag type, even if the tag will
43362015 /// not be stored at runtime.
4337 pub fn unionTagTypeHypothetical(ty: Type) Type {
4338 const union_obj = ty.cast(Payload.Union).?.data;
2016 pub fn unionTagTypeHypothetical(ty: Type, mod: *Module) Type {
2017 const union_obj = mod.typeToUnion(ty).?;
43392018 assert(union_obj.haveFieldTypes());
43402019 return union_obj.tag_ty;
43412020 }
43422021
4343 pub fn unionFields(ty: Type) Module.Union.Fields {
4344 const union_obj = ty.cast(Payload.Union).?.data;
2022 pub fn unionFields(ty: Type, mod: *Module) Module.Union.Fields {
2023 const union_obj = mod.typeToUnion(ty).?;
43452024 assert(union_obj.haveFieldTypes());
43462025 return union_obj.fields;
43472026 }
43482027
43492028 pub fn unionFieldType(ty: Type, enum_tag: Value, mod: *Module) Type {
4350 const union_obj = ty.cast(Payload.Union).?.data;
2029 const union_obj = mod.typeToUnion(ty).?;
43512030 const index = ty.unionTagFieldIndex(enum_tag, mod).?;
43522031 assert(union_obj.haveFieldTypes());
43532032 return union_obj.fields.values()[index].ty;
43542033 }
43552034
43562035 pub fn unionTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?usize {
4357 const union_obj = ty.cast(Payload.Union).?.data;
2036 const union_obj = mod.typeToUnion(ty).?;
43582037 const index = union_obj.tag_ty.enumTagFieldIndex(enum_tag, mod) orelse return null;
4359 const name = union_obj.tag_ty.enumFieldName(index);
2038 const name = union_obj.tag_ty.enumFieldName(index, mod);
43602039 return union_obj.fields.getIndex(name);
43612040 }
43622041
4363 pub fn unionHasAllZeroBitFieldTypes(ty: Type) bool {
4364 return ty.cast(Payload.Union).?.data.hasAllZeroBitFieldTypes();
2042 pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *Module) bool {
2043 const union_obj = mod.typeToUnion(ty).?;
2044 return union_obj.hasAllZeroBitFieldTypes(mod);
43652045 }
43662046
4367 pub fn unionGetLayout(ty: Type, target: Target) Module.Union.Layout {
4368 switch (ty.tag()) {
4369 .@"union" => {
4370 const union_obj = ty.castTag(.@"union").?.data;
4371 return union_obj.getLayout(target, false);
4372 },
4373 .union_safety_tagged, .union_tagged => {
4374 const union_obj = ty.cast(Payload.Union).?.data;
4375 return union_obj.getLayout(target, true);
4376 },
4377 else => unreachable,
4378 }
2047 pub fn unionGetLayout(ty: Type, mod: *Module) Module.Union.Layout {
2048 const union_type = mod.intern_pool.indexToKey(ty.toIntern()).union_type;
2049 const union_obj = mod.unionPtr(union_type.index);
2050 return union_obj.getLayout(mod, union_type.hasTag());
43792051 }
43802052
4381 pub fn containerLayout(ty: Type) std.builtin.Type.ContainerLayout {
4382 return switch (ty.tag()) {
4383 .tuple, .empty_struct_literal, .anon_struct => .Auto,
4384 .@"struct" => ty.castTag(.@"struct").?.data.layout,
4385 .@"union" => ty.castTag(.@"union").?.data.layout,
4386 .union_safety_tagged => ty.castTag(.union_safety_tagged).?.data.layout,
4387 .union_tagged => ty.castTag(.union_tagged).?.data.layout,
2053 pub fn containerLayout(ty: Type, mod: *Module) std.builtin.Type.ContainerLayout {
2054 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2055 .struct_type => |struct_type| {
2056 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .Auto;
2057 return struct_obj.layout;
2058 },
2059 .anon_struct_type => .Auto,
2060 .union_type => |union_type| {
2061 const union_obj = mod.unionPtr(union_type.index);
2062 return union_obj.layout;
2063 },
43882064 else => unreachable,
43892065 };
43902066 }
43912067
43922068 /// Asserts that the type is an error union.
4393 pub fn errorUnionPayload(self: Type) Type {
4394 return switch (self.tag()) {
4395 .anyerror_void_error_union => Type.initTag(.void),
4396 .error_union => self.castTag(.error_union).?.data.payload,
4397 else => unreachable,
4398 };
2069 pub fn errorUnionPayload(ty: Type, mod: *Module) Type {
2070 return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.payload_type.toType();
43992071 }
44002072
4401 pub fn errorUnionSet(self: Type) Type {
4402 return switch (self.tag()) {
4403 .anyerror_void_error_union => Type.initTag(.anyerror),
4404 .error_union => self.castTag(.error_union).?.data.error_set,
4405 else => unreachable,
4406 };
2073 /// Asserts that the type is an error union.
2074 pub fn errorUnionSet(ty: Type, mod: *Module) Type {
2075 return mod.intern_pool.indexToKey(ty.toIntern()).error_union_type.error_set_type.toType();
44072076 }
44082077
44092078 /// Returns false for unresolved inferred error sets.
4410 pub fn errorSetIsEmpty(ty: Type) bool {
4411 switch (ty.tag()) {
4412 .anyerror => return false,
4413 .error_set_inferred => {
4414 const inferred_error_set = ty.castTag(.error_set_inferred).?.data;
4415 // Can't know for sure.
4416 if (!inferred_error_set.is_resolved) return false;
4417 if (inferred_error_set.is_anyerror) return false;
4418 return inferred_error_set.errors.count() == 0;
4419 },
4420 .error_set_single => return false,
4421 .error_set => {
4422 const err_set_obj = ty.castTag(.error_set).?.data;
4423 return err_set_obj.names.count() == 0;
4424 },
4425 .error_set_merged => {
4426 const name_map = ty.castTag(.error_set_merged).?.data;
4427 return name_map.count() == 0;
2079 pub fn errorSetIsEmpty(ty: Type, mod: *Module) bool {
2080 return switch (ty.toIntern()) {
2081 .anyerror_type => false,
2082 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2083 .error_set_type => |error_set_type| error_set_type.names.len == 0,
2084 .inferred_error_set_type => |index| {
2085 const inferred_error_set = mod.inferredErrorSetPtr(index);
2086 // Can't know for sure.
2087 if (!inferred_error_set.is_resolved) return false;
2088 if (inferred_error_set.is_anyerror) return false;
2089 return inferred_error_set.errors.count() == 0;
2090 },
2091 else => unreachable,
44282092 },
4429 else => unreachable,
4430 }
2093 };
44312094 }
44322095
44332096 /// Returns true if it is an error set that includes anyerror, false otherwise.
44342097 /// Note that the result may be a false negative if the type did not get error set
44352098 /// resolution prior to this call.
4436 pub fn isAnyError(ty: Type) bool {
4437 return switch (ty.tag()) {
4438 .anyerror => true,
4439 .error_set_inferred => ty.castTag(.error_set_inferred).?.data.is_anyerror,
4440 else => false,
2099 pub fn isAnyError(ty: Type, mod: *Module) bool {
2100 return switch (ty.toIntern()) {
2101 .anyerror_type => true,
2102 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2103 .inferred_error_set_type => |i| mod.inferredErrorSetPtr(i).is_anyerror,
2104 else => false,
2105 },
44412106 };
44422107 }
44432108
4444 pub fn isError(ty: Type) bool {
4445 return switch (ty.zigTypeTag()) {
2109 pub fn isError(ty: Type, mod: *const Module) bool {
2110 return switch (ty.zigTypeTag(mod)) {
44462111 .ErrorUnion, .ErrorSet => true,
44472112 else => false,
44482113 };
......@@ -4451,230 +2116,221 @@ pub const Type = extern union {
44512116 /// Returns whether ty, which must be an error set, includes an error `name`.
44522117 /// Might return a false negative if `ty` is an inferred error set and not fully
44532118 /// resolved yet.
4454 pub fn errorSetHasField(ty: Type, name: []const u8) bool {
4455 if (ty.isAnyError()) {
4456 return true;
4457 }
4458
4459 switch (ty.tag()) {
4460 .error_set_single => {
4461 const data = ty.castTag(.error_set_single).?.data;
4462 return std.mem.eql(u8, data, name);
4463 },
4464 .error_set_inferred => {
4465 const data = ty.castTag(.error_set_inferred).?.data;
4466 return data.errors.contains(name);
4467 },
4468 .error_set_merged => {
4469 const data = ty.castTag(.error_set_merged).?.data;
4470 return data.contains(name);
2119 pub fn errorSetHasFieldIp(
2120 ip: *const InternPool,
2121 ty: InternPool.Index,
2122 name: InternPool.NullTerminatedString,
2123 ) bool {
2124 return switch (ty) {
2125 .anyerror_type => true,
2126 else => switch (ip.indexToKey(ty)) {
2127 .error_set_type => |error_set_type| {
2128 return error_set_type.nameIndex(ip, name) != null;
2129 },
2130 .inferred_error_set_type => |index| {
2131 const ies = ip.inferredErrorSetPtrConst(index);
2132 if (ies.is_anyerror) return true;
2133 return ies.errors.contains(name);
2134 },
2135 else => unreachable,
44712136 },
4472 .error_set => {
4473 const data = ty.castTag(.error_set).?.data;
4474 return data.names.contains(name);
2137 };
2138 }
2139
2140 /// Returns whether ty, which must be an error set, includes an error `name`.
2141 /// Might return a false negative if `ty` is an inferred error set and not fully
2142 /// resolved yet.
2143 pub fn errorSetHasField(ty: Type, name: []const u8, mod: *Module) bool {
2144 const ip = &mod.intern_pool;
2145 return switch (ty.toIntern()) {
2146 .anyerror_type => true,
2147 else => switch (ip.indexToKey(ty.toIntern())) {
2148 .error_set_type => |error_set_type| {
2149 // If the string is not interned, then the field certainly is not present.
2150 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2151 return error_set_type.nameIndex(ip, field_name_interned) != null;
2152 },
2153 .inferred_error_set_type => |index| {
2154 const ies = ip.inferredErrorSetPtr(index);
2155 if (ies.is_anyerror) return true;
2156 // If the string is not interned, then the field certainly is not present.
2157 const field_name_interned = ip.getString(name).unwrap() orelse return false;
2158 return ies.errors.contains(field_name_interned);
2159 },
2160 else => unreachable,
44752161 },
4476 else => unreachable,
4477 }
2162 };
44782163 }
44792164
44802165 /// Asserts the type is an array or vector or struct.
4481 pub fn arrayLen(ty: Type) u64 {
4482 return switch (ty.tag()) {
4483 .vector => ty.castTag(.vector).?.data.len,
4484 .array => ty.castTag(.array).?.data.len,
4485 .array_sentinel => ty.castTag(.array_sentinel).?.data.len,
4486 .array_u8 => ty.castTag(.array_u8).?.data,
4487 .array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,
4488 .tuple => ty.castTag(.tuple).?.data.types.len,
4489 .anon_struct => ty.castTag(.anon_struct).?.data.types.len,
4490 .@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
4491 .empty_struct, .empty_struct_literal => 0,
2166 pub fn arrayLen(ty: Type, mod: *const Module) u64 {
2167 return arrayLenIp(ty, &mod.intern_pool);
2168 }
2169
2170 pub fn arrayLenIp(ty: Type, ip: *const InternPool) u64 {
2171 return switch (ip.indexToKey(ty.toIntern())) {
2172 .vector_type => |vector_type| vector_type.len,
2173 .array_type => |array_type| array_type.len,
2174 .struct_type => |struct_type| {
2175 const struct_obj = ip.structPtrUnwrapConst(struct_type.index) orelse return 0;
2176 return struct_obj.fields.count();
2177 },
2178 .anon_struct_type => |tuple| tuple.types.len,
44922179
44932180 else => unreachable,
44942181 };
44952182 }
44962183
4497 pub fn arrayLenIncludingSentinel(ty: Type) u64 {
4498 return ty.arrayLen() + @boolToInt(ty.sentinel() != null);
2184 pub fn arrayLenIncludingSentinel(ty: Type, mod: *const Module) u64 {
2185 return ty.arrayLen(mod) + @boolToInt(ty.sentinel(mod) != null);
44992186 }
45002187
4501 pub fn vectorLen(ty: Type) u32 {
4502 return switch (ty.tag()) {
4503 .vector => @intCast(u32, ty.castTag(.vector).?.data.len),
4504 .tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),
4505 .anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len),
2188 pub fn vectorLen(ty: Type, mod: *const Module) u32 {
2189 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2190 .vector_type => |vector_type| vector_type.len,
2191 .anon_struct_type => |tuple| @intCast(u32, tuple.types.len),
45062192 else => unreachable,
45072193 };
45082194 }
45092195
45102196 /// Asserts the type is an array, pointer or vector.
4511 pub fn sentinel(self: Type) ?Value {
4512 return switch (self.tag()) {
4513 .single_const_pointer,
4514 .single_mut_pointer,
4515 .many_const_pointer,
4516 .many_mut_pointer,
4517 .c_const_pointer,
4518 .c_mut_pointer,
4519 .single_const_pointer_to_comptime_int,
4520 .vector,
4521 .array,
4522 .array_u8,
4523 .manyptr_u8,
4524 .manyptr_const_u8,
4525 .const_slice_u8,
4526 .const_slice,
4527 .mut_slice,
4528 .tuple,
4529 .empty_struct_literal,
4530 .@"struct",
4531 => return null,
4532
4533 .pointer => return self.castTag(.pointer).?.data.sentinel,
4534 .array_sentinel => return self.castTag(.array_sentinel).?.data.sentinel,
4535
4536 .array_u8_sentinel_0,
4537 .const_slice_u8_sentinel_0,
4538 .manyptr_const_u8_sentinel_0,
4539 => return Value.zero,
2197 pub fn sentinel(ty: Type, mod: *const Module) ?Value {
2198 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2199 .vector_type,
2200 .struct_type,
2201 .anon_struct_type,
2202 => null,
2203
2204 .array_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,
2205 .ptr_type => |t| if (t.sentinel != .none) t.sentinel.toValue() else null,
45402206
45412207 else => unreachable,
45422208 };
45432209 }
45442210
45452211 /// Returns true if and only if the type is a fixed-width integer.
4546 pub fn isInt(self: Type) bool {
4547 return self.isSignedInt() or self.isUnsignedInt();
2212 pub fn isInt(self: Type, mod: *const Module) bool {
2213 return self.isSignedInt(mod) or self.isUnsignedInt(mod);
45482214 }
45492215
45502216 /// Returns true if and only if the type is a fixed-width, signed integer.
4551 pub fn isSignedInt(self: Type) bool {
4552 return switch (self.tag()) {
4553 .int_signed,
4554 .i8,
4555 .isize,
4556 .c_char,
4557 .c_short,
4558 .c_int,
4559 .c_long,
4560 .c_longlong,
4561 .i16,
4562 .i32,
4563 .i64,
4564 .i128,
4565 => true,
4566
4567 else => false,
2217 pub fn isSignedInt(ty: Type, mod: *const Module) bool {
2218 return switch (ty.toIntern()) {
2219 .c_char_type, .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true,
2220 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2221 .int_type => |int_type| int_type.signedness == .signed,
2222 else => false,
2223 },
45682224 };
45692225 }
45702226
45712227 /// Returns true if and only if the type is a fixed-width, unsigned integer.
4572 pub fn isUnsignedInt(self: Type) bool {
4573 return switch (self.tag()) {
4574 .int_unsigned,
4575 .usize,
4576 .c_ushort,
4577 .c_uint,
4578 .c_ulong,
4579 .c_ulonglong,
4580 .u1,
4581 .u8,
4582 .u16,
4583 .u29,
4584 .u32,
4585 .u64,
4586 .u128,
4587 => true,
4588
4589 else => false,
2228 pub fn isUnsignedInt(ty: Type, mod: *const Module) bool {
2229 return switch (ty.toIntern()) {
2230 .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true,
2231 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2232 .int_type => |int_type| int_type.signedness == .unsigned,
2233 else => false,
2234 },
45902235 };
45912236 }
45922237
45932238 /// Returns true for integers, enums, error sets, and packed structs.
45942239 /// If this function returns true, then intInfo() can be called on the type.
4595 pub fn isAbiInt(ty: Type) bool {
4596 return switch (ty.zigTypeTag()) {
2240 pub fn isAbiInt(ty: Type, mod: *Module) bool {
2241 return switch (ty.zigTypeTag(mod)) {
45972242 .Int, .Enum, .ErrorSet => true,
4598 .Struct => ty.containerLayout() == .Packed,
2243 .Struct => ty.containerLayout(mod) == .Packed,
45992244 else => false,
46002245 };
46012246 }
46022247
46032248 /// Asserts the type is an integer, enum, error set, or vector of one of them.
4604 pub fn intInfo(self: Type, target: Target) std.builtin.Type.Int {
4605 var ty = self;
4606 while (true) switch (ty.tag()) {
4607 .int_unsigned => return .{
4608 .signedness = .unsigned,
4609 .bits = ty.castTag(.int_unsigned).?.data,
4610 },
4611 .int_signed => return .{
4612 .signedness = .signed,
4613 .bits = ty.castTag(.int_signed).?.data,
4614 },
4615 .u1 => return .{ .signedness = .unsigned, .bits = 1 },
4616 .u8 => return .{ .signedness = .unsigned, .bits = 8 },
4617 .i8 => return .{ .signedness = .signed, .bits = 8 },
4618 .u16 => return .{ .signedness = .unsigned, .bits = 16 },
4619 .i16 => return .{ .signedness = .signed, .bits = 16 },
4620 .u29 => return .{ .signedness = .unsigned, .bits = 29 },
4621 .u32 => return .{ .signedness = .unsigned, .bits = 32 },
4622 .i32 => return .{ .signedness = .signed, .bits = 32 },
4623 .u64 => return .{ .signedness = .unsigned, .bits = 64 },
4624 .i64 => return .{ .signedness = .signed, .bits = 64 },
4625 .u128 => return .{ .signedness = .unsigned, .bits = 128 },
4626 .i128 => return .{ .signedness = .signed, .bits = 128 },
4627 .usize => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
4628 .isize => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
4629 .c_char => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.char) },
4630 .c_short => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
4631 .c_ushort => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
4632 .c_int => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
4633 .c_uint => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.uint) },
4634 .c_long => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.long) },
4635 .c_ulong => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulong) },
4636 .c_longlong => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.longlong) },
4637 .c_ulonglong => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
4638
4639 .enum_full, .enum_nonexhaustive => ty = ty.cast(Payload.EnumFull).?.data.tag_ty,
4640 .enum_numbered => ty = ty.castTag(.enum_numbered).?.data.tag_ty,
4641 .enum_simple => {
4642 const enum_obj = ty.castTag(.enum_simple).?.data;
4643 const field_count = enum_obj.fields.count();
4644 if (field_count == 0) return .{ .signedness = .unsigned, .bits = 0 };
4645 return .{ .signedness = .unsigned, .bits = smallestUnsignedBits(field_count - 1) };
4646 },
2249 pub fn intInfo(starting_ty: Type, mod: *Module) InternPool.Key.IntType {
2250 const target = mod.getTarget();
2251 var ty = starting_ty;
46472252
4648 .error_set, .error_set_single, .anyerror, .error_set_inferred, .error_set_merged => {
2253 while (true) switch (ty.toIntern()) {
2254 .anyerror_type => {
46492255 // TODO revisit this when error sets support custom int types
46502256 return .{ .signedness = .unsigned, .bits = 16 };
46512257 },
2258 .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() },
2259 .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() },
2260 .c_char_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.char) },
2261 .c_short_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.short) },
2262 .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ushort) },
2263 .c_int_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.int) },
2264 .c_uint_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.uint) },
2265 .c_long_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.long) },
2266 .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulong) },
2267 .c_longlong_type => return .{ .signedness = .signed, .bits = target.c_type_bit_size(.longlong) },
2268 .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.c_type_bit_size(.ulonglong) },
2269 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2270 .int_type => |int_type| return int_type,
2271 .struct_type => |struct_type| {
2272 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
2273 assert(struct_obj.layout == .Packed);
2274 ty = struct_obj.backing_int_ty;
2275 },
2276 .enum_type => |enum_type| ty = enum_type.tag_ty.toType(),
2277 .vector_type => |vector_type| ty = vector_type.child.toType(),
46522278
4653 .vector => ty = ty.castTag(.vector).?.data.elem_type,
4654
4655 .@"struct" => {
4656 const struct_obj = ty.castTag(.@"struct").?.data;
4657 assert(struct_obj.layout == .Packed);
4658 ty = struct_obj.backing_int_ty;
4659 },
4660
4661 else => unreachable,
4662 };
4663 }
4664
4665 pub fn isNamedInt(self: Type) bool {
4666 return switch (self.tag()) {
4667 .usize,
4668 .isize,
4669 .c_char,
4670 .c_short,
4671 .c_ushort,
4672 .c_int,
4673 .c_uint,
4674 .c_long,
4675 .c_ulong,
4676 .c_longlong,
4677 .c_ulonglong,
2279 // TODO revisit this when error sets support custom int types
2280 .error_set_type, .inferred_error_set_type => return .{ .signedness = .unsigned, .bits = 16 },
2281
2282 .anon_struct_type => unreachable,
2283
2284 .ptr_type => unreachable,
2285 .anyframe_type => unreachable,
2286 .array_type => unreachable,
2287
2288 .opt_type => unreachable,
2289 .error_union_type => unreachable,
2290 .func_type => unreachable,
2291 .simple_type => unreachable, // handled via Index enum tag above
2292
2293 .union_type => unreachable,
2294 .opaque_type => unreachable,
2295
2296 // values, not types
2297 .undef,
2298 .runtime_value,
2299 .simple_value,
2300 .variable,
2301 .extern_func,
2302 .func,
2303 .int,
2304 .err,
2305 .error_union,
2306 .enum_literal,
2307 .enum_tag,
2308 .empty_enum_value,
2309 .float,
2310 .ptr,
2311 .opt,
2312 .aggregate,
2313 .un,
2314 // memoization, not types
2315 .memoized_call,
2316 => unreachable,
2317 },
2318 };
2319 }
2320
2321 pub fn isNamedInt(ty: Type) bool {
2322 return switch (ty.toIntern()) {
2323 .usize_type,
2324 .isize_type,
2325 .c_char_type,
2326 .c_short_type,
2327 .c_ushort_type,
2328 .c_int_type,
2329 .c_uint_type,
2330 .c_long_type,
2331 .c_ulong_type,
2332 .c_longlong_type,
2333 .c_ulonglong_type,
46782334 => true,
46792335
46802336 else => false,
......@@ -4682,14 +2338,14 @@ pub const Type = extern union {
46822338 }
46832339
46842340 /// Returns `false` for `comptime_float`.
4685 pub fn isRuntimeFloat(self: Type) bool {
4686 return switch (self.tag()) {
4687 .f16,
4688 .f32,
4689 .f64,
4690 .f80,
4691 .f128,
4692 .c_longdouble,
2341 pub fn isRuntimeFloat(ty: Type) bool {
2342 return switch (ty.toIntern()) {
2343 .f16_type,
2344 .f32_type,
2345 .f64_type,
2346 .f80_type,
2347 .f128_type,
2348 .c_longdouble_type,
46932349 => true,
46942350
46952351 else => false,
......@@ -4697,15 +2353,15 @@ pub const Type = extern union {
46972353 }
46982354
46992355 /// Returns `true` for `comptime_float`.
4700 pub fn isAnyFloat(self: Type) bool {
4701 return switch (self.tag()) {
4702 .f16,
4703 .f32,
4704 .f64,
4705 .f80,
4706 .f128,
4707 .c_longdouble,
4708 .comptime_float,
2356 pub fn isAnyFloat(ty: Type) bool {
2357 return switch (ty.toIntern()) {
2358 .f16_type,
2359 .f32_type,
2360 .f64_type,
2361 .f80_type,
2362 .f128_type,
2363 .c_longdouble_type,
2364 .comptime_float_type,
47092365 => true,
47102366
47112367 else => false,
......@@ -4714,431 +2370,304 @@ pub const Type = extern union {
47142370
47152371 /// Asserts the type is a fixed-size float or comptime_float.
47162372 /// Returns 128 for comptime_float types.
4717 pub fn floatBits(self: Type, target: Target) u16 {
4718 return switch (self.tag()) {
4719 .f16 => 16,
4720 .f32 => 32,
4721 .f64 => 64,
4722 .f80 => 80,
4723 .f128, .comptime_float => 128,
4724 .c_longdouble => target.c_type_bit_size(.longdouble),
4725
4726 else => unreachable,
4727 };
4728 }
4729
4730 /// Asserts the type is a function.
4731 pub fn fnParamLen(self: Type) usize {
4732 return switch (self.tag()) {
4733 .fn_noreturn_no_args => 0,
4734 .fn_void_no_args => 0,
4735 .fn_naked_noreturn_no_args => 0,
4736 .fn_ccc_void_no_args => 0,
4737 .function => self.castTag(.function).?.data.param_types.len,
2373 pub fn floatBits(ty: Type, target: Target) u16 {
2374 return switch (ty.toIntern()) {
2375 .f16_type => 16,
2376 .f32_type => 32,
2377 .f64_type => 64,
2378 .f80_type => 80,
2379 .f128_type, .comptime_float_type => 128,
2380 .c_longdouble_type => target.c_type_bit_size(.longdouble),
47382381
47392382 else => unreachable,
47402383 };
47412384 }
47422385
4743 /// Asserts the type is a function. The length of the slice must be at least the length
4744 /// given by `fnParamLen`.
4745 pub fn fnParamTypes(self: Type, types: []Type) void {
4746 switch (self.tag()) {
4747 .fn_noreturn_no_args => return,
4748 .fn_void_no_args => return,
4749 .fn_naked_noreturn_no_args => return,
4750 .fn_ccc_void_no_args => return,
4751 .function => {
4752 const payload = self.castTag(.function).?.data;
4753 @memcpy(types[0..payload.param_types.len], payload.param_types);
4754 },
4755
4756 else => unreachable,
4757 }
4758 }
4759
4760 /// Asserts the type is a function.
4761 pub fn fnParamType(self: Type, index: usize) Type {
4762 switch (self.tag()) {
4763 .function => {
4764 const payload = self.castTag(.function).?.data;
4765 return payload.param_types[index];
4766 },
4767
4768 else => unreachable,
4769 }
4770 }
4771
4772 /// Asserts the type is a function.
4773 pub fn fnReturnType(self: Type) Type {
4774 return switch (self.tag()) {
4775 .fn_noreturn_no_args => Type.initTag(.noreturn),
4776 .fn_naked_noreturn_no_args => Type.initTag(.noreturn),
4777
4778 .fn_void_no_args,
4779 .fn_ccc_void_no_args,
4780 => Type.initTag(.void),
4781
4782 .function => self.castTag(.function).?.data.return_type,
4783
4784 else => unreachable,
4785 };
2386 /// Asserts the type is a function or a function pointer.
2387 pub fn fnReturnType(ty: Type, mod: *Module) Type {
2388 return fnReturnTypeIp(ty, &mod.intern_pool);
47862389 }
47872390
4788 /// Asserts the type is a function.
4789 pub fn fnCallingConvention(self: Type) std.builtin.CallingConvention {
4790 return switch (self.tag()) {
4791 .fn_noreturn_no_args => .Unspecified,
4792 .fn_void_no_args => .Unspecified,
4793 .fn_naked_noreturn_no_args => .Naked,
4794 .fn_ccc_void_no_args => .C,
4795 .function => self.castTag(.function).?.data.cc,
4796
2391 pub fn fnReturnTypeIp(ty: Type, ip: *const InternPool) Type {
2392 return switch (ip.indexToKey(ty.toIntern())) {
2393 .ptr_type => |ptr_type| ip.indexToKey(ptr_type.child).func_type.return_type,
2394 .func_type => |func_type| func_type.return_type,
47972395 else => unreachable,
4798 };
2396 }.toType();
47992397 }
48002398
48012399 /// Asserts the type is a function.
4802 pub fn fnCallingConventionAllowsZigTypes(target: Target, cc: std.builtin.CallingConvention) bool {
4803 return switch (cc) {
4804 .Unspecified, .Async, .Inline => true,
4805 // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI.
4806 // The goal is to experiment with more integrated CPU/GPU code.
4807 .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64,
4808 else => false,
4809 };
2400 pub fn fnCallingConvention(ty: Type, mod: *Module) std.builtin.CallingConvention {
2401 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.cc;
48102402 }
48112403
4812 pub fn isValidParamType(self: Type) bool {
4813 return switch (self.zigTypeTagOrPoison() catch return true) {
2404 pub fn isValidParamType(self: Type, mod: *const Module) bool {
2405 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
48142406 .Undefined, .Null, .Opaque, .NoReturn => false,
48152407 else => true,
48162408 };
48172409 }
48182410
4819 pub fn isValidReturnType(self: Type) bool {
4820 return switch (self.zigTypeTagOrPoison() catch return true) {
2411 pub fn isValidReturnType(self: Type, mod: *const Module) bool {
2412 return switch (self.zigTypeTagOrPoison(mod) catch return true) {
48212413 .Undefined, .Null, .Opaque => false,
48222414 else => true,
48232415 };
48242416 }
48252417
48262418 /// Asserts the type is a function.
4827 pub fn fnIsVarArgs(self: Type) bool {
4828 return switch (self.tag()) {
4829 .fn_noreturn_no_args => false,
4830 .fn_void_no_args => false,
4831 .fn_naked_noreturn_no_args => false,
4832 .fn_ccc_void_no_args => false,
4833 .function => self.castTag(.function).?.data.is_var_args,
4834
4835 else => unreachable,
4836 };
4837 }
4838
4839 pub fn fnInfo(ty: Type) Payload.Function.Data {
4840 return switch (ty.tag()) {
4841 .fn_noreturn_no_args => .{
4842 .param_types = &.{},
4843 .comptime_params = undefined,
4844 .return_type = initTag(.noreturn),
4845 .cc = .Unspecified,
4846 .alignment = 0,
4847 .is_var_args = false,
4848 .is_generic = false,
4849 .is_noinline = false,
4850 .align_is_generic = false,
4851 .cc_is_generic = false,
4852 .section_is_generic = false,
4853 .addrspace_is_generic = false,
4854 .noalias_bits = 0,
4855 },
4856 .fn_void_no_args => .{
4857 .param_types = &.{},
4858 .comptime_params = undefined,
4859 .return_type = initTag(.void),
4860 .cc = .Unspecified,
4861 .alignment = 0,
4862 .is_var_args = false,
4863 .is_generic = false,
4864 .is_noinline = false,
4865 .align_is_generic = false,
4866 .cc_is_generic = false,
4867 .section_is_generic = false,
4868 .addrspace_is_generic = false,
4869 .noalias_bits = 0,
4870 },
4871 .fn_naked_noreturn_no_args => .{
4872 .param_types = &.{},
4873 .comptime_params = undefined,
4874 .return_type = initTag(.noreturn),
4875 .cc = .Naked,
4876 .alignment = 0,
4877 .is_var_args = false,
4878 .is_generic = false,
4879 .is_noinline = false,
4880 .align_is_generic = false,
4881 .cc_is_generic = false,
4882 .section_is_generic = false,
4883 .addrspace_is_generic = false,
4884 .noalias_bits = 0,
4885 },
4886 .fn_ccc_void_no_args => .{
4887 .param_types = &.{},
4888 .comptime_params = undefined,
4889 .return_type = initTag(.void),
4890 .cc = .C,
4891 .alignment = 0,
4892 .is_var_args = false,
4893 .is_generic = false,
4894 .is_noinline = false,
4895 .align_is_generic = false,
4896 .cc_is_generic = false,
4897 .section_is_generic = false,
4898 .addrspace_is_generic = false,
4899 .noalias_bits = 0,
4900 },
4901 .function => ty.castTag(.function).?.data,
4902
4903 else => unreachable,
4904 };
4905 }
4906
4907 pub fn isNumeric(self: Type) bool {
4908 return switch (self.tag()) {
4909 .f16,
4910 .f32,
4911 .f64,
4912 .f80,
4913 .f128,
4914 .c_longdouble,
4915 .comptime_int,
4916 .comptime_float,
4917 .u1,
4918 .u8,
4919 .i8,
4920 .u16,
4921 .i16,
4922 .u29,
4923 .u32,
4924 .i32,
4925 .u64,
4926 .i64,
4927 .u128,
4928 .i128,
4929 .usize,
4930 .isize,
4931 .c_char,
4932 .c_short,
4933 .c_ushort,
4934 .c_int,
4935 .c_uint,
4936 .c_long,
4937 .c_ulong,
4938 .c_longlong,
4939 .c_ulonglong,
4940 .int_unsigned,
4941 .int_signed,
2419 pub fn fnIsVarArgs(ty: Type, mod: *Module) bool {
2420 return mod.intern_pool.indexToKey(ty.toIntern()).func_type.is_var_args;
2421 }
2422
2423 pub fn isNumeric(ty: Type, mod: *const Module) bool {
2424 return switch (ty.toIntern()) {
2425 .f16_type,
2426 .f32_type,
2427 .f64_type,
2428 .f80_type,
2429 .f128_type,
2430 .c_longdouble_type,
2431 .comptime_int_type,
2432 .comptime_float_type,
2433 .usize_type,
2434 .isize_type,
2435 .c_char_type,
2436 .c_short_type,
2437 .c_ushort_type,
2438 .c_int_type,
2439 .c_uint_type,
2440 .c_long_type,
2441 .c_ulong_type,
2442 .c_longlong_type,
2443 .c_ulonglong_type,
49422444 => true,
49432445
4944 else => false,
2446 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2447 .int_type => true,
2448 else => false,
2449 },
49452450 };
49462451 }
49472452
49482453 /// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
49492454 /// resolves field types rather than asserting they are already resolved.
4950 pub fn onePossibleValue(starting_type: Type) ?Value {
2455 pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
49512456 var ty = starting_type;
4952 while (true) switch (ty.tag()) {
4953 .f16,
4954 .f32,
4955 .f64,
4956 .f80,
4957 .f128,
4958 .c_longdouble,
4959 .comptime_int,
4960 .comptime_float,
4961 .u1,
4962 .u8,
4963 .i8,
4964 .u16,
4965 .i16,
4966 .u29,
4967 .u32,
4968 .i32,
4969 .u64,
4970 .i64,
4971 .u128,
4972 .i128,
4973 .usize,
4974 .isize,
4975 .c_char,
4976 .c_short,
4977 .c_ushort,
4978 .c_int,
4979 .c_uint,
4980 .c_long,
4981 .c_ulong,
4982 .c_longlong,
4983 .c_ulonglong,
4984 .bool,
4985 .type,
4986 .anyerror,
4987 .error_union,
4988 .error_set_single,
4989 .error_set,
4990 .error_set_merged,
4991 .fn_noreturn_no_args,
4992 .fn_void_no_args,
4993 .fn_naked_noreturn_no_args,
4994 .fn_ccc_void_no_args,
4995 .function,
4996 .single_const_pointer_to_comptime_int,
4997 .array_sentinel,
4998 .array_u8_sentinel_0,
4999 .const_slice_u8,
5000 .const_slice_u8_sentinel_0,
5001 .const_slice,
5002 .mut_slice,
5003 .anyopaque,
5004 .optional_single_mut_pointer,
5005 .optional_single_const_pointer,
5006 .enum_literal,
5007 .anyerror_void_error_union,
5008 .error_set_inferred,
5009 .@"opaque",
5010 .manyptr_u8,
5011 .manyptr_const_u8,
5012 .manyptr_const_u8_sentinel_0,
5013 .atomic_order,
5014 .atomic_rmw_op,
5015 .calling_convention,
5016 .address_space,
5017 .float_mode,
5018 .reduce_op,
5019 .modifier,
5020 .prefetch_options,
5021 .export_options,
5022 .extern_options,
5023 .type_info,
5024 .@"anyframe",
5025 .anyframe_T,
5026 .many_const_pointer,
5027 .many_mut_pointer,
5028 .c_const_pointer,
5029 .c_mut_pointer,
5030 .single_const_pointer,
5031 .single_mut_pointer,
5032 .pointer,
5033 => return null,
5034
5035 .optional => {
5036 var buf: Payload.ElemType = undefined;
5037 const child_ty = ty.optionalChild(&buf);
5038 if (child_ty.isNoReturn()) {
5039 return Value.null;
5040 } else {
5041 return null;
5042 }
5043 },
50442457
5045 .@"struct" => {
5046 const s = ty.castTag(.@"struct").?.data;
5047 assert(s.haveFieldTypes());
5048 for (s.fields.values()) |field| {
5049 if (field.is_comptime) continue;
5050 if (field.ty.onePossibleValue() != null) continue;
5051 return null;
5052 }
5053 return Value.initTag(.empty_struct_value);
5054 },
2458 while (true) switch (ty.toIntern()) {
2459 .empty_struct_type => return Value.empty_struct,
50552460
5056 .tuple, .anon_struct => {
5057 const tuple = ty.tupleFields();
5058 for (tuple.values, 0..) |val, i| {
5059 const is_comptime = val.tag() != .unreachable_value;
5060 if (is_comptime) continue;
5061 if (tuple.types[i].onePossibleValue() != null) continue;
5062 return null;
5063 }
5064 return Value.initTag(.empty_struct_value);
5065 },
2461 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2462 .int_type => |int_type| {
2463 if (int_type.bits == 0) {
2464 return try mod.intValue(ty, 0);
2465 } else {
2466 return null;
2467 }
2468 },
50662469
5067 .enum_numbered => {
5068 const enum_numbered = ty.castTag(.enum_numbered).?.data;
5069 // An explicit tag type is always provided for enum_numbered.
5070 if (enum_numbered.tag_ty.hasRuntimeBits()) {
5071 return null;
5072 }
5073 assert(enum_numbered.fields.count() == 1);
5074 return enum_numbered.values.keys()[0];
5075 },
5076 .enum_full => {
5077 const enum_full = ty.castTag(.enum_full).?.data;
5078 if (enum_full.tag_ty.hasRuntimeBits()) {
2470 .ptr_type,
2471 .error_union_type,
2472 .func_type,
2473 .anyframe_type,
2474 .error_set_type,
2475 .inferred_error_set_type,
2476 => return null,
2477
2478 inline .array_type, .vector_type => |seq_type, seq_tag| {
2479 const has_sentinel = seq_tag == .array_type and seq_type.sentinel != .none;
2480 if (seq_type.len + @boolToInt(has_sentinel) == 0) return (try mod.intern(.{ .aggregate = .{
2481 .ty = ty.toIntern(),
2482 .storage = .{ .elems = &.{} },
2483 } })).toValue();
2484 if (try seq_type.child.toType().onePossibleValue(mod)) |opv| {
2485 return (try mod.intern(.{ .aggregate = .{
2486 .ty = ty.toIntern(),
2487 .storage = .{ .repeated_elem = opv.toIntern() },
2488 } })).toValue();
2489 }
50792490 return null;
5080 }
5081 switch (enum_full.fields.count()) {
5082 0 => return Value.initTag(.unreachable_value),
5083 1 => if (enum_full.values.count() == 0) {
5084 return Value.zero; // auto-numbered
2491 },
2492 .opt_type => |child| {
2493 if (child == .noreturn_type) {
2494 return try mod.nullValue(ty);
50852495 } else {
5086 return enum_full.values.keys()[0];
2496 return null;
2497 }
2498 },
2499
2500 .simple_type => |t| switch (t) {
2501 .f16,
2502 .f32,
2503 .f64,
2504 .f80,
2505 .f128,
2506 .usize,
2507 .isize,
2508 .c_char,
2509 .c_short,
2510 .c_ushort,
2511 .c_int,
2512 .c_uint,
2513 .c_long,
2514 .c_ulong,
2515 .c_longlong,
2516 .c_ulonglong,
2517 .c_longdouble,
2518 .anyopaque,
2519 .bool,
2520 .type,
2521 .anyerror,
2522 .comptime_int,
2523 .comptime_float,
2524 .enum_literal,
2525 .atomic_order,
2526 .atomic_rmw_op,
2527 .calling_convention,
2528 .address_space,
2529 .float_mode,
2530 .reduce_op,
2531 .call_modifier,
2532 .prefetch_options,
2533 .export_options,
2534 .extern_options,
2535 .type_info,
2536 => return null,
2537
2538 .void => return Value.void,
2539 .noreturn => return Value.@"unreachable",
2540 .null => return Value.null,
2541 .undefined => return Value.undef,
2542
2543 .generic_poison => unreachable,
2544 },
2545 .struct_type => |struct_type| {
2546 if (mod.structPtrUnwrap(struct_type.index)) |s| {
2547 assert(s.haveFieldTypes());
2548 const field_vals = try mod.gpa.alloc(InternPool.Index, s.fields.count());
2549 defer mod.gpa.free(field_vals);
2550 for (field_vals, s.fields.values()) |*field_val, field| {
2551 if (field.is_comptime) {
2552 field_val.* = field.default_val;
2553 continue;
2554 }
2555 if (try field.ty.onePossibleValue(mod)) |field_opv| {
2556 field_val.* = try field_opv.intern(field.ty, mod);
2557 } else return null;
2558 }
2559
2560 // In this case the struct has no runtime-known fields and
2561 // therefore has one possible value.
2562 return (try mod.intern(.{ .aggregate = .{
2563 .ty = ty.toIntern(),
2564 .storage = .{ .elems = field_vals },
2565 } })).toValue();
2566 }
2567
2568 // In this case the struct has no fields at all and
2569 // therefore has one possible value.
2570 return (try mod.intern(.{ .aggregate = .{
2571 .ty = ty.toIntern(),
2572 .storage = .{ .elems = &.{} },
2573 } })).toValue();
2574 },
2575
2576 .anon_struct_type => |tuple| {
2577 for (tuple.values) |val| {
2578 if (val == .none) return null;
2579 }
2580 // In this case the struct has all comptime-known fields and
2581 // therefore has one possible value.
2582 // TODO: write something like getCoercedInts to avoid needing to dupe
2583 const duped_values = try mod.gpa.dupe(InternPool.Index, tuple.values);
2584 defer mod.gpa.free(duped_values);
2585 return (try mod.intern(.{ .aggregate = .{
2586 .ty = ty.toIntern(),
2587 .storage = .{ .elems = duped_values },
2588 } })).toValue();
2589 },
2590
2591 .union_type => |union_type| {
2592 const union_obj = mod.unionPtr(union_type.index);
2593 const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null;
2594 if (union_obj.fields.count() == 0) {
2595 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2596 return only.toValue();
2597 }
2598 const only_field = union_obj.fields.values()[0];
2599 const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null;
2600 const only = try mod.intern(.{ .un = .{
2601 .ty = ty.toIntern(),
2602 .tag = tag_val.toIntern(),
2603 .val = val_val.toIntern(),
2604 } });
2605 return only.toValue();
2606 },
2607 .opaque_type => return null,
2608 .enum_type => |enum_type| switch (enum_type.tag_mode) {
2609 .nonexhaustive => {
2610 if (enum_type.tag_ty == .comptime_int_type) return null;
2611
2612 if (try enum_type.tag_ty.toType().onePossibleValue(mod)) |int_opv| {
2613 const only = try mod.intern(.{ .enum_tag = .{
2614 .ty = ty.toIntern(),
2615 .int = int_opv.toIntern(),
2616 } });
2617 return only.toValue();
2618 }
2619
2620 return null;
50872621 },
5088 else => return null,
5089 }
5090 },
5091 .enum_simple => {
5092 const enum_simple = ty.castTag(.enum_simple).?.data;
5093 switch (enum_simple.fields.count()) {
5094 0 => return Value.initTag(.unreachable_value),
5095 1 => return Value.zero,
5096 else => return null,
5097 }
5098 },
5099 .enum_nonexhaustive => {
5100 const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
5101 if (!tag_ty.hasRuntimeBits()) {
5102 return Value.zero;
5103 } else {
5104 return null;
5105 }
5106 },
5107 .@"union", .union_safety_tagged, .union_tagged => {
5108 const union_obj = ty.cast(Payload.Union).?.data;
5109 const tag_val = union_obj.tag_ty.onePossibleValue() orelse return null;
5110 if (union_obj.fields.count() == 0) return Value.initTag(.unreachable_value);
5111 const only_field = union_obj.fields.values()[0];
5112 const val_val = only_field.ty.onePossibleValue() orelse return null;
5113 _ = tag_val;
5114 _ = val_val;
5115 return Value.initTag(.empty_struct_value);
5116 },
2622 .auto, .explicit => {
2623 if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
51172624
5118 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
5119 .void => return Value.initTag(.void_value),
5120 .noreturn => return Value.initTag(.unreachable_value),
5121 .null => return Value.initTag(.null_value),
5122 .undefined => return Value.initTag(.undef),
2625 switch (enum_type.names.len) {
2626 0 => {
2627 const only = try mod.intern(.{ .empty_enum_value = ty.toIntern() });
2628 return only.toValue();
2629 },
2630 1 => {
2631 if (enum_type.values.len == 0) {
2632 const only = try mod.intern(.{ .enum_tag = .{
2633 .ty = ty.toIntern(),
2634 .int = try mod.intern(.{ .int = .{
2635 .ty = enum_type.tag_ty,
2636 .storage = .{ .u64 = 0 },
2637 } }),
2638 } });
2639 return only.toValue();
2640 } else {
2641 return enum_type.values[0].toValue();
2642 }
2643 },
2644 else => return null,
2645 }
2646 },
2647 },
51232648
5124 .int_unsigned, .int_signed => {
5125 if (ty.cast(Payload.Bits).?.data == 0) {
5126 return Value.zero;
5127 } else {
5128 return null;
5129 }
5130 },
5131 .vector, .array, .array_u8 => {
5132 if (ty.arrayLen() == 0)
5133 return Value.initTag(.empty_array);
5134 if (ty.elemType().onePossibleValue() != null)
5135 return Value.initTag(.the_only_possible_value);
5136 return null;
2649 // values, not types
2650 .undef,
2651 .runtime_value,
2652 .simple_value,
2653 .variable,
2654 .extern_func,
2655 .func,
2656 .int,
2657 .err,
2658 .error_union,
2659 .enum_literal,
2660 .enum_tag,
2661 .empty_enum_value,
2662 .float,
2663 .ptr,
2664 .opt,
2665 .aggregate,
2666 .un,
2667 // memoization, not types
2668 .memoized_call,
2669 => unreachable,
51372670 },
5138
5139 .inferred_alloc_const => unreachable,
5140 .inferred_alloc_mut => unreachable,
5141 .generic_poison => unreachable,
51422671 };
51432672 }
51442673
......@@ -5146,350 +2675,298 @@ pub const Type = extern union {
51462675 /// resolves field types rather than asserting they are already resolved.
51472676 /// TODO merge these implementations together with the "advanced" pattern seen
51482677 /// elsewhere in this file.
5149 pub fn comptimeOnly(ty: Type) bool {
5150 return switch (ty.tag()) {
5151 .u1,
5152 .u8,
5153 .i8,
5154 .u16,
5155 .i16,
5156 .u29,
5157 .u32,
5158 .i32,
5159 .u64,
5160 .i64,
5161 .u128,
5162 .i128,
5163 .usize,
5164 .isize,
5165 .c_char,
5166 .c_short,
5167 .c_ushort,
5168 .c_int,
5169 .c_uint,
5170 .c_long,
5171 .c_ulong,
5172 .c_longlong,
5173 .c_ulonglong,
5174 .c_longdouble,
5175 .f16,
5176 .f32,
5177 .f64,
5178 .f80,
5179 .f128,
5180 .anyopaque,
5181 .bool,
5182 .void,
5183 .anyerror,
5184 .noreturn,
5185 .@"anyframe",
5186 .null,
5187 .undefined,
5188 .atomic_order,
5189 .atomic_rmw_op,
5190 .calling_convention,
5191 .address_space,
5192 .float_mode,
5193 .reduce_op,
5194 .modifier,
5195 .prefetch_options,
5196 .export_options,
5197 .extern_options,
5198 .manyptr_u8,
5199 .manyptr_const_u8,
5200 .manyptr_const_u8_sentinel_0,
5201 .const_slice_u8,
5202 .const_slice_u8_sentinel_0,
5203 .anyerror_void_error_union,
5204 .empty_struct_literal,
5205 .empty_struct,
5206 .error_set,
5207 .error_set_single,
5208 .error_set_inferred,
5209 .error_set_merged,
5210 .@"opaque",
5211 .generic_poison,
5212 .array_u8,
5213 .array_u8_sentinel_0,
5214 .int_signed,
5215 .int_unsigned,
5216 .enum_simple,
5217 => false,
5218
5219 .single_const_pointer_to_comptime_int,
5220 .type,
5221 .comptime_int,
5222 .comptime_float,
5223 .enum_literal,
5224 .type_info,
5225 // These are function bodies, not function pointers.
5226 .fn_noreturn_no_args,
5227 .fn_void_no_args,
5228 .fn_naked_noreturn_no_args,
5229 .fn_ccc_void_no_args,
5230 .function,
5231 => true,
2678 pub fn comptimeOnly(ty: Type, mod: *Module) bool {
2679 return switch (ty.toIntern()) {
2680 .empty_struct_type => false,
2681
2682 else => switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2683 .int_type => false,
2684 .ptr_type => |ptr_type| {
2685 const child_ty = ptr_type.child.toType();
2686 if (child_ty.zigTypeTag(mod) == .Fn) {
2687 return false;
2688 } else {
2689 return child_ty.comptimeOnly(mod);
2690 }
2691 },
2692 .anyframe_type => |child| {
2693 if (child == .none) return false;
2694 return child.toType().comptimeOnly(mod);
2695 },
2696 .array_type => |array_type| array_type.child.toType().comptimeOnly(mod),
2697 .vector_type => |vector_type| vector_type.child.toType().comptimeOnly(mod),
2698 .opt_type => |child| child.toType().comptimeOnly(mod),
2699 .error_union_type => |error_union_type| error_union_type.payload_type.toType().comptimeOnly(mod),
2700
2701 .error_set_type,
2702 .inferred_error_set_type,
2703 => false,
2704
2705 // These are function bodies, not function pointers.
2706 .func_type => true,
2707
2708 .simple_type => |t| switch (t) {
2709 .f16,
2710 .f32,
2711 .f64,
2712 .f80,
2713 .f128,
2714 .usize,
2715 .isize,
2716 .c_char,
2717 .c_short,
2718 .c_ushort,
2719 .c_int,
2720 .c_uint,
2721 .c_long,
2722 .c_ulong,
2723 .c_longlong,
2724 .c_ulonglong,
2725 .c_longdouble,
2726 .anyopaque,
2727 .bool,
2728 .void,
2729 .anyerror,
2730 .noreturn,
2731 .generic_poison,
2732 .atomic_order,
2733 .atomic_rmw_op,
2734 .calling_convention,
2735 .address_space,
2736 .float_mode,
2737 .reduce_op,
2738 .call_modifier,
2739 .prefetch_options,
2740 .export_options,
2741 .extern_options,
2742 => false,
2743
2744 .type,
2745 .comptime_int,
2746 .comptime_float,
2747 .null,
2748 .undefined,
2749 .enum_literal,
2750 .type_info,
2751 => true,
2752 },
2753 .struct_type => |struct_type| {
2754 // A struct with no fields is not comptime-only.
2755 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
2756 switch (struct_obj.requires_comptime) {
2757 .wip, .unknown => {
2758 // Return false to avoid incorrect dependency loops.
2759 // This will be handled correctly once merged with
2760 // `Sema.typeRequiresComptime`.
2761 return false;
2762 },
2763 .no => return false,
2764 .yes => return true,
2765 }
2766 },
52322767
5233 .inferred_alloc_mut => unreachable,
5234 .inferred_alloc_const => unreachable,
5235
5236 .array,
5237 .array_sentinel,
5238 .vector,
5239 => return ty.childType().comptimeOnly(),
5240
5241 .pointer,
5242 .single_const_pointer,
5243 .single_mut_pointer,
5244 .many_const_pointer,
5245 .many_mut_pointer,
5246 .c_const_pointer,
5247 .c_mut_pointer,
5248 .const_slice,
5249 .mut_slice,
5250 => {
5251 const child_ty = ty.childType();
5252 if (child_ty.zigTypeTag() == .Fn) {
2768 .anon_struct_type => |tuple| {
2769 for (tuple.types, tuple.values) |field_ty, val| {
2770 const have_comptime_val = val != .none;
2771 if (!have_comptime_val and field_ty.toType().comptimeOnly(mod)) return true;
2772 }
52532773 return false;
5254 } else {
5255 return child_ty.comptimeOnly();
5256 }
5257 },
5258
5259 .optional,
5260 .optional_single_mut_pointer,
5261 .optional_single_const_pointer,
5262 => {
5263 var buf: Type.Payload.ElemType = undefined;
5264 return ty.optionalChild(&buf).comptimeOnly();
5265 },
2774 },
52662775
5267 .tuple, .anon_struct => {
5268 const tuple = ty.tupleFields();
5269 for (tuple.types, 0..) |field_ty, i| {
5270 const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
5271 if (!have_comptime_val and field_ty.comptimeOnly()) return true;
5272 }
5273 return false;
5274 },
2776 .union_type => |union_type| {
2777 const union_obj = mod.unionPtr(union_type.index);
2778 switch (union_obj.requires_comptime) {
2779 .wip, .unknown => {
2780 // Return false to avoid incorrect dependency loops.
2781 // This will be handled correctly once merged with
2782 // `Sema.typeRequiresComptime`.
2783 return false;
2784 },
2785 .no => return false,
2786 .yes => return true,
2787 }
2788 },
52752789
5276 .@"struct" => {
5277 const struct_obj = ty.castTag(.@"struct").?.data;
5278 switch (struct_obj.requires_comptime) {
5279 .wip, .unknown => {
5280 // Return false to avoid incorrect dependency loops.
5281 // This will be handled correctly once merged with
5282 // `Sema.typeRequiresComptime`.
5283 return false;
5284 },
5285 .no => return false,
5286 .yes => return true,
5287 }
5288 },
2790 .opaque_type => false,
52892791
5290 .@"union", .union_safety_tagged, .union_tagged => {
5291 const union_obj = ty.cast(Type.Payload.Union).?.data;
5292 switch (union_obj.requires_comptime) {
5293 .wip, .unknown => {
5294 // Return false to avoid incorrect dependency loops.
5295 // This will be handled correctly once merged with
5296 // `Sema.typeRequiresComptime`.
5297 return false;
5298 },
5299 .no => return false,
5300 .yes => return true,
5301 }
5302 },
2792 .enum_type => |enum_type| enum_type.tag_ty.toType().comptimeOnly(mod),
53032793
5304 .error_union => return ty.errorUnionPayload().comptimeOnly(),
5305 .anyframe_T => {
5306 const child_ty = ty.castTag(.anyframe_T).?.data;
5307 return child_ty.comptimeOnly();
5308 },
5309 .enum_numbered => {
5310 const tag_ty = ty.castTag(.enum_numbered).?.data.tag_ty;
5311 return tag_ty.comptimeOnly();
5312 },
5313 .enum_full, .enum_nonexhaustive => {
5314 const tag_ty = ty.cast(Type.Payload.EnumFull).?.data.tag_ty;
5315 return tag_ty.comptimeOnly();
2794 // values, not types
2795 .undef,
2796 .runtime_value,
2797 .simple_value,
2798 .variable,
2799 .extern_func,
2800 .func,
2801 .int,
2802 .err,
2803 .error_union,
2804 .enum_literal,
2805 .enum_tag,
2806 .empty_enum_value,
2807 .float,
2808 .ptr,
2809 .opt,
2810 .aggregate,
2811 .un,
2812 // memoization, not types
2813 .memoized_call,
2814 => unreachable,
53162815 },
53172816 };
53182817 }
53192818
5320 pub fn isArrayOrVector(ty: Type) bool {
5321 return switch (ty.zigTypeTag()) {
2819 pub fn isVector(ty: Type, mod: *const Module) bool {
2820 return ty.zigTypeTag(mod) == .Vector;
2821 }
2822
2823 pub fn isArrayOrVector(ty: Type, mod: *const Module) bool {
2824 return switch (ty.zigTypeTag(mod)) {
53222825 .Array, .Vector => true,
53232826 else => false,
53242827 };
53252828 }
53262829
5327 pub fn isIndexable(ty: Type) bool {
5328 return switch (ty.zigTypeTag()) {
2830 pub fn isIndexable(ty: Type, mod: *Module) bool {
2831 return switch (ty.zigTypeTag(mod)) {
53292832 .Array, .Vector => true,
5330 .Pointer => switch (ty.ptrSize()) {
2833 .Pointer => switch (ty.ptrSize(mod)) {
53312834 .Slice, .Many, .C => true,
5332 .One => ty.elemType().zigTypeTag() == .Array,
2835 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
53332836 },
5334 .Struct => ty.isTuple(),
2837 .Struct => ty.isTuple(mod),
53352838 else => false,
53362839 };
53372840 }
53382841
5339 pub fn indexableHasLen(ty: Type) bool {
5340 return switch (ty.zigTypeTag()) {
2842 pub fn indexableHasLen(ty: Type, mod: *Module) bool {
2843 return switch (ty.zigTypeTag(mod)) {
53412844 .Array, .Vector => true,
5342 .Pointer => switch (ty.ptrSize()) {
2845 .Pointer => switch (ty.ptrSize(mod)) {
53432846 .Many, .C => false,
53442847 .Slice => true,
5345 .One => ty.elemType().zigTypeTag() == .Array,
2848 .One => ty.childType(mod).zigTypeTag(mod) == .Array,
53462849 },
5347 .Struct => ty.isTuple(),
2850 .Struct => ty.isTuple(mod),
53482851 else => false,
53492852 };
53502853 }
53512854
53522855 /// Returns null if the type has no namespace.
5353 pub fn getNamespace(self: Type) ?*Module.Namespace {
5354 return switch (self.tag()) {
5355 .@"struct" => &self.castTag(.@"struct").?.data.namespace,
5356 .enum_full => &self.castTag(.enum_full).?.data.namespace,
5357 .enum_nonexhaustive => &self.castTag(.enum_nonexhaustive).?.data.namespace,
5358 .empty_struct => self.castTag(.empty_struct).?.data,
5359 .@"opaque" => &self.castTag(.@"opaque").?.data.namespace,
5360 .@"union" => &self.castTag(.@"union").?.data.namespace,
5361 .union_safety_tagged => &self.castTag(.union_safety_tagged).?.data.namespace,
5362 .union_tagged => &self.castTag(.union_tagged).?.data.namespace,
2856 pub fn getNamespaceIndex(ty: Type, mod: *Module) Module.Namespace.OptionalIndex {
2857 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2858 .opaque_type => |opaque_type| opaque_type.namespace.toOptional(),
2859 .struct_type => |struct_type| struct_type.namespace,
2860 .union_type => |union_type| mod.unionPtr(union_type.index).namespace.toOptional(),
2861 .enum_type => |enum_type| enum_type.namespace,
53632862
5364 else => null,
2863 else => .none,
53652864 };
53662865 }
53672866
5368 // Works for vectors and vectors of integers.
5369 pub fn minInt(ty: Type, arena: Allocator, target: Target) !Value {
5370 const scalar = try minIntScalar(ty.scalarType(), arena, target);
5371 if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) {
5372 return Value.Tag.repeated.create(arena, scalar);
5373 } else {
5374 return scalar;
5375 }
2867 /// Returns null if the type has no namespace.
2868 pub fn getNamespace(ty: Type, mod: *Module) ?*Module.Namespace {
2869 return if (getNamespaceIndex(ty, mod).unwrap()) |i| mod.namespacePtr(i) else null;
53762870 }
53772871
5378 /// Asserts that self.zigTypeTag() == .Int.
5379 pub fn minIntScalar(ty: Type, arena: Allocator, target: Target) !Value {
5380 assert(ty.zigTypeTag() == .Int);
5381 const info = ty.intInfo(target);
5382
5383 if (info.bits == 0) {
5384 return Value.initTag(.the_only_possible_value);
5385 }
2872 // Works for vectors and vectors of integers.
2873 pub fn minInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
2874 const scalar = try minIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
2875 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
2876 .ty = dest_ty.toIntern(),
2877 .storage = .{ .repeated_elem = scalar.toIntern() },
2878 } })).toValue() else scalar;
2879 }
53862880
5387 if (info.signedness == .unsigned) {
5388 return Value.zero;
5389 }
2881 /// Asserts that the type is an integer.
2882 pub fn minIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
2883 const info = ty.intInfo(mod);
2884 if (info.signedness == .unsigned) return mod.intValue(dest_ty, 0);
2885 if (info.bits == 0) return mod.intValue(dest_ty, -1);
53902886
53912887 if (std.math.cast(u6, info.bits - 1)) |shift| {
53922888 const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
5393 return Value.Tag.int_i64.create(arena, n);
2889 return mod.intValue(dest_ty, n);
53942890 }
53952891
5396 var res = try std.math.big.int.Managed.init(arena);
2892 var res = try std.math.big.int.Managed.init(mod.gpa);
2893 defer res.deinit();
2894
53972895 try res.setTwosCompIntLimit(.min, info.signedness, info.bits);
53982896
5399 const res_const = res.toConst();
5400 if (res_const.positive) {
5401 return Value.Tag.int_big_positive.create(arena, res_const.limbs);
5402 } else {
5403 return Value.Tag.int_big_negative.create(arena, res_const.limbs);
5404 }
2897 return mod.intValue_big(dest_ty, res.toConst());
54052898 }
54062899
54072900 // Works for vectors and vectors of integers.
5408 pub fn maxInt(ty: Type, arena: Allocator, target: Target) !Value {
5409 const scalar = try maxIntScalar(ty.scalarType(), arena, target);
5410 if (ty.zigTypeTag() == .Vector and scalar.tag() != .the_only_possible_value) {
5411 return Value.Tag.repeated.create(arena, scalar);
5412 } else {
5413 return scalar;
5414 }
2901 /// The returned Value will have type dest_ty.
2902 pub fn maxInt(ty: Type, mod: *Module, dest_ty: Type) !Value {
2903 const scalar = try maxIntScalar(ty.scalarType(mod), mod, dest_ty.scalarType(mod));
2904 return if (ty.zigTypeTag(mod) == .Vector) (try mod.intern(.{ .aggregate = .{
2905 .ty = dest_ty.toIntern(),
2906 .storage = .{ .repeated_elem = scalar.toIntern() },
2907 } })).toValue() else scalar;
54152908 }
54162909
5417 /// Asserts that self.zigTypeTag() == .Int.
5418 pub fn maxIntScalar(self: Type, arena: Allocator, target: Target) !Value {
5419 assert(self.zigTypeTag() == .Int);
5420 const info = self.intInfo(target);
5421
5422 if (info.bits == 0) {
5423 return Value.initTag(.the_only_possible_value);
5424 }
2910 /// The returned Value will have type dest_ty.
2911 pub fn maxIntScalar(ty: Type, mod: *Module, dest_ty: Type) !Value {
2912 const info = ty.intInfo(mod);
54252913
5426 switch (info.bits - @boolToInt(info.signedness == .signed)) {
5427 0 => return Value.zero,
5428 1 => return Value.one,
2914 switch (info.bits) {
2915 0 => return switch (info.signedness) {
2916 .signed => try mod.intValue(dest_ty, -1),
2917 .unsigned => try mod.intValue(dest_ty, 0),
2918 },
2919 1 => return switch (info.signedness) {
2920 .signed => try mod.intValue(dest_ty, 0),
2921 .unsigned => try mod.intValue(dest_ty, 1),
2922 },
54292923 else => {},
54302924 }
54312925
54322926 if (std.math.cast(u6, info.bits - 1)) |shift| switch (info.signedness) {
54332927 .signed => {
54342928 const n = @as(i64, std.math.maxInt(i64)) >> (63 - shift);
5435 return Value.Tag.int_i64.create(arena, n);
2929 return mod.intValue(dest_ty, n);
54362930 },
54372931 .unsigned => {
54382932 const n = @as(u64, std.math.maxInt(u64)) >> (63 - shift);
5439 return Value.Tag.int_u64.create(arena, n);
2933 return mod.intValue(dest_ty, n);
54402934 },
54412935 };
54422936
5443 var res = try std.math.big.int.Managed.init(arena);
2937 var res = try std.math.big.int.Managed.init(mod.gpa);
2938 defer res.deinit();
2939
54442940 try res.setTwosCompIntLimit(.max, info.signedness, info.bits);
54452941
5446 const res_const = res.toConst();
5447 if (res_const.positive) {
5448 return Value.Tag.int_big_positive.create(arena, res_const.limbs);
5449 } else {
5450 return Value.Tag.int_big_negative.create(arena, res_const.limbs);
5451 }
2942 return mod.intValue_big(dest_ty, res.toConst());
54522943 }
54532944
54542945 /// Asserts the type is an enum or a union.
5455 pub fn intTagType(ty: Type, buffer: *Payload.Bits) Type {
5456 switch (ty.tag()) {
5457 .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty,
5458 .enum_numbered => return ty.castTag(.enum_numbered).?.data.tag_ty,
5459 .enum_simple => {
5460 const enum_simple = ty.castTag(.enum_simple).?.data;
5461 const field_count = enum_simple.fields.count();
5462 const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count);
5463 buffer.* = .{
5464 .base = .{ .tag = .int_unsigned },
5465 .data = bits,
5466 };
5467 return Type.initPayload(&buffer.base);
5468 },
5469 .union_tagged => return ty.castTag(.union_tagged).?.data.tag_ty.intTagType(buffer),
2946 pub fn intTagType(ty: Type, mod: *Module) Type {
2947 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2948 .union_type => |union_type| mod.unionPtr(union_type.index).tag_ty.intTagType(mod),
2949 .enum_type => |enum_type| enum_type.tag_ty.toType(),
54702950 else => unreachable,
5471 }
2951 };
54722952 }
54732953
5474 pub fn isNonexhaustiveEnum(ty: Type) bool {
5475 return switch (ty.tag()) {
5476 .enum_nonexhaustive => true,
2954 pub fn isNonexhaustiveEnum(ty: Type, mod: *Module) bool {
2955 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2956 .enum_type => |enum_type| switch (enum_type.tag_mode) {
2957 .nonexhaustive => true,
2958 .auto, .explicit => false,
2959 },
54772960 else => false,
54782961 };
54792962 }
54802963
54812964 // Asserts that `ty` is an error set and not `anyerror`.
5482 pub fn errorSetNames(ty: Type) []const []const u8 {
5483 return switch (ty.tag()) {
5484 .error_set_single => blk: {
5485 // Work around coercion problems
5486 const tmp: *const [1][]const u8 = &ty.castTag(.error_set_single).?.data;
5487 break :blk tmp;
5488 },
5489 .error_set_merged => ty.castTag(.error_set_merged).?.data.keys(),
5490 .error_set => ty.castTag(.error_set).?.data.names.keys(),
5491 .error_set_inferred => {
5492 const inferred_error_set = ty.castTag(.error_set_inferred).?.data;
2965 pub fn errorSetNames(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2966 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
2967 .error_set_type => |x| x.names,
2968 .inferred_error_set_type => |index| {
2969 const inferred_error_set = mod.inferredErrorSetPtr(index);
54932970 assert(inferred_error_set.is_resolved);
54942971 assert(!inferred_error_set.is_anyerror);
54952972 return inferred_error_set.errors.keys();
......@@ -5498,133 +2975,43 @@ pub const Type = extern union {
54982975 };
54992976 }
55002977
5501 /// Merge lhs with rhs.
5502 /// Asserts that lhs and rhs are both error sets and are resolved.
5503 pub fn errorSetMerge(lhs: Type, arena: Allocator, rhs: Type) !Type {
5504 const lhs_names = lhs.errorSetNames();
5505 const rhs_names = rhs.errorSetNames();
5506 var names: Module.ErrorSet.NameMap = .{};
5507 try names.ensureUnusedCapacity(arena, lhs_names.len);
5508 for (lhs_names) |name| {
5509 names.putAssumeCapacityNoClobber(name, {});
5510 }
5511 for (rhs_names) |name| {
5512 try names.put(arena, name, {});
5513 }
5514
5515 // names must be sorted
5516 Module.ErrorSet.sortNames(&names);
5517
5518 return try Tag.error_set_merged.create(arena, names);
5519 }
5520
5521 pub fn enumFields(ty: Type) Module.EnumFull.NameMap {
5522 return switch (ty.tag()) {
5523 .enum_full, .enum_nonexhaustive => ty.cast(Payload.EnumFull).?.data.fields,
5524 .enum_simple => ty.castTag(.enum_simple).?.data.fields,
5525 .enum_numbered => ty.castTag(.enum_numbered).?.data.fields,
5526 .atomic_order,
5527 .atomic_rmw_op,
5528 .calling_convention,
5529 .address_space,
5530 .float_mode,
5531 .reduce_op,
5532 .modifier,
5533 .prefetch_options,
5534 .export_options,
5535 .extern_options,
5536 => @panic("TODO resolve std.builtin types"),
5537 else => unreachable,
5538 };
2978 pub fn enumFields(ty: Type, mod: *Module) []const InternPool.NullTerminatedString {
2979 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names;
55392980 }
55402981
5541 pub fn enumFieldCount(ty: Type) usize {
5542 return ty.enumFields().count();
2982 pub fn enumFieldCount(ty: Type, mod: *Module) usize {
2983 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names.len;
55432984 }
55442985
5545 pub fn enumFieldName(ty: Type, field_index: usize) []const u8 {
5546 return ty.enumFields().keys()[field_index];
2986 pub fn enumFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
2987 return mod.intern_pool.indexToKey(ty.toIntern()).enum_type.names[field_index];
55472988 }
55482989
5549 pub fn enumFieldIndex(ty: Type, field_name: []const u8) ?usize {
5550 return ty.enumFields().getIndex(field_name);
2990 pub fn enumFieldIndex(ty: Type, field_name: InternPool.NullTerminatedString, mod: *Module) ?u32 {
2991 const ip = &mod.intern_pool;
2992 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
2993 return enum_type.nameIndex(ip, field_name);
55512994 }
55522995
55532996 /// Asserts `ty` is an enum. `enum_tag` can either be `enum_field_index` or
55542997 /// an integer which represents the enum value. Returns the field index in
55552998 /// declaration order, or `null` if `enum_tag` does not match any field.
5556 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?usize {
5557 if (enum_tag.castTag(.enum_field_index)) |payload| {
5558 return @as(usize, payload.data);
5559 }
5560 const S = struct {
5561 fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {
5562 if (int_val.compareAllWithZero(.lt, m)) return null;
5563 var end_payload: Value.Payload.U64 = .{
5564 .base = .{ .tag = .int_u64 },
5565 .data = end,
5566 };
5567 const end_val = Value.initPayload(&end_payload.base);
5568 if (int_val.compareAll(.gte, end_val, int_ty, m)) return null;
5569 return @intCast(usize, int_val.toUnsignedInt(m.getTarget()));
5570 }
5571 };
5572 switch (ty.tag()) {
5573 .enum_full, .enum_nonexhaustive => {
5574 const enum_full = ty.cast(Payload.EnumFull).?.data;
5575 const tag_ty = enum_full.tag_ty;
5576 if (enum_full.values.count() == 0) {
5577 return S.fieldWithRange(tag_ty, enum_tag, enum_full.fields.count(), mod);
5578 } else {
5579 return enum_full.values.getIndexContext(enum_tag, .{
5580 .ty = tag_ty,
5581 .mod = mod,
5582 });
5583 }
5584 },
5585 .enum_numbered => {
5586 const enum_obj = ty.castTag(.enum_numbered).?.data;
5587 const tag_ty = enum_obj.tag_ty;
5588 if (enum_obj.values.count() == 0) {
5589 return S.fieldWithRange(tag_ty, enum_tag, enum_obj.fields.count(), mod);
5590 } else {
5591 return enum_obj.values.getIndexContext(enum_tag, .{
5592 .ty = tag_ty,
5593 .mod = mod,
5594 });
5595 }
5596 },
5597 .enum_simple => {
5598 const enum_simple = ty.castTag(.enum_simple).?.data;
5599 const fields_len = enum_simple.fields.count();
5600 const bits = std.math.log2_int_ceil(usize, fields_len);
5601 var buffer: Payload.Bits = .{
5602 .base = .{ .tag = .int_unsigned },
5603 .data = bits,
5604 };
5605 const tag_ty = Type.initPayload(&buffer.base);
5606 return S.fieldWithRange(tag_ty, enum_tag, fields_len, mod);
5607 },
5608 .atomic_order,
5609 .atomic_rmw_op,
5610 .calling_convention,
5611 .address_space,
5612 .float_mode,
5613 .reduce_op,
5614 .modifier,
5615 .prefetch_options,
5616 .export_options,
5617 .extern_options,
5618 => @panic("TODO resolve std.builtin types"),
2999 pub fn enumTagFieldIndex(ty: Type, enum_tag: Value, mod: *Module) ?u32 {
3000 const ip = &mod.intern_pool;
3001 const enum_type = ip.indexToKey(ty.toIntern()).enum_type;
3002 const int_tag = switch (ip.indexToKey(enum_tag.toIntern())) {
3003 .int => enum_tag.toIntern(),
3004 .enum_tag => |info| info.int,
56193005 else => unreachable,
5620 }
3006 };
3007 assert(ip.typeOf(int_tag) == enum_type.tag_ty);
3008 return enum_type.tagValueIndex(ip, int_tag);
56213009 }
56223010
5623 pub fn structFields(ty: Type) Module.Struct.Fields {
5624 switch (ty.tag()) {
5625 .empty_struct, .empty_struct_literal => return .{},
5626 .@"struct" => {
5627 const struct_obj = ty.castTag(.@"struct").?.data;
3011 pub fn structFields(ty: Type, mod: *Module) Module.Struct.Fields {
3012 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3013 .struct_type => |struct_type| {
3014 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return .{};
56283015 assert(struct_obj.haveFieldTypes());
56293016 return struct_obj.fields;
56303017 },
......@@ -5632,141 +3019,122 @@ pub const Type = extern union {
56323019 }
56333020 }
56343021
5635 pub fn structFieldName(ty: Type, field_index: usize) []const u8 {
5636 switch (ty.tag()) {
5637 .@"struct" => {
5638 const struct_obj = ty.castTag(.@"struct").?.data;
3022 pub fn structFieldName(ty: Type, field_index: usize, mod: *Module) InternPool.NullTerminatedString {
3023 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3024 .struct_type => |struct_type| {
3025 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
56393026 assert(struct_obj.haveFieldTypes());
56403027 return struct_obj.fields.keys()[field_index];
56413028 },
5642 .anon_struct => return ty.castTag(.anon_struct).?.data.names[field_index],
3029 .anon_struct_type => |anon_struct| anon_struct.names[field_index],
56433030 else => unreachable,
5644 }
3031 };
56453032 }
56463033
5647 pub fn structFieldCount(ty: Type) usize {
5648 switch (ty.tag()) {
5649 .@"struct" => {
5650 const struct_obj = ty.castTag(.@"struct").?.data;
3034 pub fn structFieldCount(ty: Type, mod: *Module) usize {
3035 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3036 .struct_type => |struct_type| {
3037 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return 0;
56513038 assert(struct_obj.haveFieldTypes());
56523039 return struct_obj.fields.count();
56533040 },
5654 .empty_struct, .empty_struct_literal => return 0,
5655 .tuple => return ty.castTag(.tuple).?.data.types.len,
5656 .anon_struct => return ty.castTag(.anon_struct).?.data.types.len,
3041 .anon_struct_type => |anon_struct| anon_struct.types.len,
56573042 else => unreachable,
5658 }
3043 };
56593044 }
56603045
56613046 /// Supports structs and unions.
5662 pub fn structFieldType(ty: Type, index: usize) Type {
5663 switch (ty.tag()) {
5664 .@"struct" => {
5665 const struct_obj = ty.castTag(.@"struct").?.data;
3047 pub fn structFieldType(ty: Type, index: usize, mod: *Module) Type {
3048 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3049 .struct_type => |struct_type| {
3050 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
56663051 return struct_obj.fields.values()[index].ty;
56673052 },
5668 .@"union", .union_safety_tagged, .union_tagged => {
5669 const union_obj = ty.cast(Payload.Union).?.data;
3053 .union_type => |union_type| {
3054 const union_obj = mod.unionPtr(union_type.index);
56703055 return union_obj.fields.values()[index].ty;
56713056 },
5672 .tuple => return ty.castTag(.tuple).?.data.types[index],
5673 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
3057 .anon_struct_type => |anon_struct| anon_struct.types[index].toType(),
56743058 else => unreachable,
5675 }
3059 };
56763060 }
56773061
5678 pub fn structFieldAlign(ty: Type, index: usize, target: Target) u32 {
5679 switch (ty.tag()) {
5680 .@"struct" => {
5681 const struct_obj = ty.castTag(.@"struct").?.data;
3062 pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 {
3063 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3064 .struct_type => |struct_type| {
3065 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
56823066 assert(struct_obj.layout != .Packed);
5683 return struct_obj.fields.values()[index].alignment(target, struct_obj.layout);
3067 return struct_obj.fields.values()[index].alignment(mod, struct_obj.layout);
3068 },
3069 .anon_struct_type => |anon_struct| {
3070 return anon_struct.types[index].toType().abiAlignment(mod);
56843071 },
5685 .@"union", .union_safety_tagged, .union_tagged => {
5686 const union_obj = ty.cast(Payload.Union).?.data;
5687 return union_obj.fields.values()[index].normalAlignment(target);
3072 .union_type => |union_type| {
3073 const union_obj = mod.unionPtr(union_type.index);
3074 return union_obj.fields.values()[index].normalAlignment(mod);
56883075 },
5689 .tuple => return ty.castTag(.tuple).?.data.types[index].abiAlignment(target),
5690 .anon_struct => return ty.castTag(.anon_struct).?.data.types[index].abiAlignment(target),
56913076 else => unreachable,
56923077 }
56933078 }
56943079
5695 pub fn structFieldDefaultValue(ty: Type, index: usize) Value {
5696 switch (ty.tag()) {
5697 .@"struct" => {
5698 const struct_obj = ty.castTag(.@"struct").?.data;
5699 return struct_obj.fields.values()[index].default_val;
3080 pub fn structFieldDefaultValue(ty: Type, index: usize, mod: *Module) Value {
3081 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3082 .struct_type => |struct_type| {
3083 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
3084 const val = struct_obj.fields.values()[index].default_val;
3085 // TODO: avoid using `unreachable` to indicate this.
3086 if (val == .none) return Value.@"unreachable";
3087 return val.toValue();
57003088 },
5701 .tuple => {
5702 const tuple = ty.castTag(.tuple).?.data;
5703 return tuple.values[index];
5704 },
5705 .anon_struct => {
5706 const struct_obj = ty.castTag(.anon_struct).?.data;
5707 return struct_obj.values[index];
3089 .anon_struct_type => |anon_struct| {
3090 const val = anon_struct.values[index];
3091 // TODO: avoid using `unreachable` to indicate this.
3092 if (val == .none) return Value.@"unreachable";
3093 return val.toValue();
57083094 },
57093095 else => unreachable,
57103096 }
57113097 }
57123098
5713 pub fn structFieldValueComptime(ty: Type, index: usize) ?Value {
5714 switch (ty.tag()) {
5715 .@"struct" => {
5716 const struct_obj = ty.castTag(.@"struct").?.data;
3099 pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
3100 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3101 .struct_type => |struct_type| {
3102 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
57173103 const field = struct_obj.fields.values()[index];
57183104 if (field.is_comptime) {
5719 return field.default_val;
3105 return field.default_val.toValue();
57203106 } else {
5721 return field.ty.onePossibleValue();
3107 return field.ty.onePossibleValue(mod);
57223108 }
57233109 },
5724 .tuple => {
5725 const tuple = ty.castTag(.tuple).?.data;
3110 .anon_struct_type => |tuple| {
57263111 const val = tuple.values[index];
5727 if (val.tag() == .unreachable_value) {
5728 return tuple.types[index].onePossibleValue();
5729 } else {
5730 return val;
5731 }
5732 },
5733 .anon_struct => {
5734 const anon_struct = ty.castTag(.anon_struct).?.data;
5735 const val = anon_struct.values[index];
5736 if (val.tag() == .unreachable_value) {
5737 return anon_struct.types[index].onePossibleValue();
3112 if (val == .none) {
3113 return tuple.types[index].toType().onePossibleValue(mod);
57383114 } else {
5739 return val;
3115 return val.toValue();
57403116 }
57413117 },
57423118 else => unreachable,
57433119 }
57443120 }
57453121
5746 pub fn structFieldIsComptime(ty: Type, index: usize) bool {
5747 switch (ty.tag()) {
5748 .@"struct" => {
5749 const struct_obj = ty.castTag(.@"struct").?.data;
3122 pub fn structFieldIsComptime(ty: Type, index: usize, mod: *Module) bool {
3123 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3124 .struct_type => |struct_type| {
3125 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
57503126 if (struct_obj.layout == .Packed) return false;
57513127 const field = struct_obj.fields.values()[index];
57523128 return field.is_comptime;
57533129 },
5754 .tuple => {
5755 const tuple = ty.castTag(.tuple).?.data;
5756 const val = tuple.values[index];
5757 return val.tag() != .unreachable_value;
5758 },
5759 .anon_struct => {
5760 const anon_struct = ty.castTag(.anon_struct).?.data;
5761 const val = anon_struct.values[index];
5762 return val.tag() != .unreachable_value;
5763 },
3130 .anon_struct_type => |anon_struct| anon_struct.values[index] != .none,
57643131 else => unreachable,
5765 }
3132 };
57663133 }
57673134
5768 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, target: Target) u32 {
5769 const struct_obj = ty.castTag(.@"struct").?.data;
3135 pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 {
3136 const struct_type = mod.intern_pool.indexToKey(ty.toIntern()).struct_type;
3137 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
57703138 assert(struct_obj.layout == .Packed);
57713139 comptime assert(Type.packed_struct_layout_version == 2);
57723140
......@@ -5774,9 +3142,9 @@ pub const Type = extern union {
57743142 var elem_size_bits: u16 = undefined;
57753143 var running_bits: u16 = 0;
57763144 for (struct_obj.fields.values(), 0..) |f, i| {
5777 if (!f.ty.hasRuntimeBits()) continue;
3145 if (!f.ty.hasRuntimeBits(mod)) continue;
57783146
5779 const field_bits = @intCast(u16, f.ty.bitSize(target));
3147 const field_bits = @intCast(u16, f.ty.bitSize(mod));
57803148 if (i == field_index) {
57813149 bit_offset = running_bits;
57823150 elem_size_bits = field_bits;
......@@ -5797,9 +3165,10 @@ pub const Type = extern union {
57973165 offset: u64 = 0,
57983166 big_align: u32 = 0,
57993167 struct_obj: *Module.Struct,
5800 target: Target,
3168 module: *Module,
58013169
58023170 pub fn next(it: *StructOffsetIterator) ?FieldOffset {
3171 const mod = it.module;
58033172 var i = it.field;
58043173 if (it.struct_obj.fields.count() <= i)
58053174 return null;
......@@ -5811,35 +3180,36 @@ pub const Type = extern union {
58113180 const field = it.struct_obj.fields.values()[i];
58123181 it.field += 1;
58133182
5814 if (field.is_comptime or !field.ty.hasRuntimeBits()) {
3183 if (field.is_comptime or !field.ty.hasRuntimeBits(mod)) {
58153184 return FieldOffset{ .field = i, .offset = it.offset };
58163185 }
58173186
5818 const field_align = field.alignment(it.target, it.struct_obj.layout);
3187 const field_align = field.alignment(mod, it.struct_obj.layout);
58193188 it.big_align = @max(it.big_align, field_align);
58203189 const field_offset = std.mem.alignForwardGeneric(u64, it.offset, field_align);
5821 it.offset = field_offset + field.ty.abiSize(it.target);
3190 it.offset = field_offset + field.ty.abiSize(mod);
58223191 return FieldOffset{ .field = i, .offset = field_offset };
58233192 }
58243193 };
58253194
58263195 /// Get an iterator that iterates over all the struct field, returning the field and
58273196 /// offset of that field. Asserts that the type is a non-packed struct.
5828 pub fn iterateStructOffsets(ty: Type, target: Target) StructOffsetIterator {
5829 const struct_obj = ty.castTag(.@"struct").?.data;
3197 pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator {
3198 const struct_type = mod.intern_pool.indexToKey(ty.toIntern()).struct_type;
3199 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
58303200 assert(struct_obj.haveLayout());
58313201 assert(struct_obj.layout != .Packed);
5832 return .{ .struct_obj = struct_obj, .target = target };
3202 return .{ .struct_obj = struct_obj, .module = mod };
58333203 }
58343204
58353205 /// Supports structs and unions.
5836 pub fn structFieldOffset(ty: Type, index: usize, target: Target) u64 {
5837 switch (ty.tag()) {
5838 .@"struct" => {
5839 const struct_obj = ty.castTag(.@"struct").?.data;
3206 pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 {
3207 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3208 .struct_type => |struct_type| {
3209 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
58403210 assert(struct_obj.haveLayout());
58413211 assert(struct_obj.layout != .Packed);
5842 var it = ty.iterateStructOffsets(target);
3212 var it = ty.iterateStructOffsets(mod);
58433213 while (it.next()) |field_offset| {
58443214 if (index == field_offset.field)
58453215 return field_offset.offset;
......@@ -5848,34 +3218,32 @@ pub const Type = extern union {
58483218 return std.mem.alignForwardGeneric(u64, it.offset, @max(it.big_align, 1));
58493219 },
58503220
5851 .tuple, .anon_struct => {
5852 const tuple = ty.tupleFields();
5853
3221 .anon_struct_type => |tuple| {
58543222 var offset: u64 = 0;
58553223 var big_align: u32 = 0;
58563224
5857 for (tuple.types, 0..) |field_ty, i| {
5858 const field_val = tuple.values[i];
5859 if (field_val.tag() != .unreachable_value or !field_ty.hasRuntimeBits()) {
3225 for (tuple.types, tuple.values, 0..) |field_ty, field_val, i| {
3226 if (field_val != .none or !field_ty.toType().hasRuntimeBits(mod)) {
58603227 // comptime field
58613228 if (i == index) return offset;
58623229 continue;
58633230 }
58643231
5865 const field_align = field_ty.abiAlignment(target);
3232 const field_align = field_ty.toType().abiAlignment(mod);
58663233 big_align = @max(big_align, field_align);
58673234 offset = std.mem.alignForwardGeneric(u64, offset, field_align);
58683235 if (i == index) return offset;
5869 offset += field_ty.abiSize(target);
3236 offset += field_ty.toType().abiSize(mod);
58703237 }
58713238 offset = std.mem.alignForwardGeneric(u64, offset, @max(big_align, 1));
58723239 return offset;
58733240 },
58743241
5875 .@"union" => return 0,
5876 .union_safety_tagged, .union_tagged => {
5877 const union_obj = ty.cast(Payload.Union).?.data;
5878 const layout = union_obj.getLayout(target, true);
3242 .union_type => |union_type| {
3243 if (!union_type.hasTag())
3244 return 0;
3245 const union_obj = mod.unionPtr(union_type.index);
3246 const layout = union_obj.getLayout(mod, true);
58793247 if (layout.tag_align >= layout.payload_align) {
58803248 // {Tag, Payload}
58813249 return std.mem.alignForwardGeneric(u64, layout.tag_size, layout.payload_align);
......@@ -5884,6 +3252,7 @@ pub const Type = extern union {
58843252 return 0;
58853253 }
58863254 },
3255
58873256 else => unreachable,
58883257 }
58893258 }
......@@ -5893,507 +3262,92 @@ pub const Type = extern union {
58933262 }
58943263
58953264 pub fn declSrcLocOrNull(ty: Type, mod: *Module) ?Module.SrcLoc {
5896 switch (ty.tag()) {
5897 .enum_full, .enum_nonexhaustive => {
5898 const enum_full = ty.cast(Payload.EnumFull).?.data;
5899 return enum_full.srcLoc(mod);
5900 },
5901 .enum_numbered => {
5902 const enum_numbered = ty.castTag(.enum_numbered).?.data;
5903 return enum_numbered.srcLoc(mod);
5904 },
5905 .enum_simple => {
5906 const enum_simple = ty.castTag(.enum_simple).?.data;
5907 return enum_simple.srcLoc(mod);
5908 },
5909 .@"struct" => {
5910 const struct_obj = ty.castTag(.@"struct").?.data;
3265 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3266 .struct_type => |struct_type| {
3267 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
59113268 return struct_obj.srcLoc(mod);
59123269 },
5913 .error_set => {
5914 const error_set = ty.castTag(.error_set).?.data;
5915 return error_set.srcLoc(mod);
5916 },
5917 .@"union", .union_safety_tagged, .union_tagged => {
5918 const union_obj = ty.cast(Payload.Union).?.data;
3270 .union_type => |union_type| {
3271 const union_obj = mod.unionPtr(union_type.index);
59193272 return union_obj.srcLoc(mod);
59203273 },
5921 .@"opaque" => {
5922 const opaque_obj = ty.cast(Payload.Opaque).?.data;
5923 return opaque_obj.srcLoc(mod);
5924 },
5925 .atomic_order,
5926 .atomic_rmw_op,
5927 .calling_convention,
5928 .address_space,
5929 .float_mode,
5930 .reduce_op,
5931 .modifier,
5932 .prefetch_options,
5933 .export_options,
5934 .extern_options,
5935 .type_info,
5936 => unreachable, // needed to call resolveTypeFields first
5937
5938 else => return null,
5939 }
3274 .opaque_type => |opaque_type| mod.opaqueSrcLoc(opaque_type),
3275 .enum_type => |enum_type| mod.declPtr(enum_type.decl).srcLoc(mod),
3276 else => null,
3277 };
59403278 }
59413279
5942 pub fn getOwnerDecl(ty: Type) Module.Decl.Index {
5943 return ty.getOwnerDeclOrNull() orelse unreachable;
3280 pub fn getOwnerDecl(ty: Type, mod: *Module) Module.Decl.Index {
3281 return ty.getOwnerDeclOrNull(mod) orelse unreachable;
59443282 }
59453283
5946 pub fn getOwnerDeclOrNull(ty: Type) ?Module.Decl.Index {
5947 switch (ty.tag()) {
5948 .enum_full, .enum_nonexhaustive => {
5949 const enum_full = ty.cast(Payload.EnumFull).?.data;
5950 return enum_full.owner_decl;
5951 },
5952 .enum_numbered => return ty.castTag(.enum_numbered).?.data.owner_decl,
5953 .enum_simple => {
5954 const enum_simple = ty.castTag(.enum_simple).?.data;
5955 return enum_simple.owner_decl;
5956 },
5957 .@"struct" => {
5958 const struct_obj = ty.castTag(.@"struct").?.data;
3284 pub fn getOwnerDeclOrNull(ty: Type, mod: *Module) ?Module.Decl.Index {
3285 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3286 .struct_type => |struct_type| {
3287 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return null;
59593288 return struct_obj.owner_decl;
59603289 },
5961 .error_set => {
5962 const error_set = ty.castTag(.error_set).?.data;
5963 return error_set.owner_decl;
5964 },
5965 .@"union", .union_safety_tagged, .union_tagged => {
5966 const union_obj = ty.cast(Payload.Union).?.data;
3290 .union_type => |union_type| {
3291 const union_obj = mod.unionPtr(union_type.index);
59673292 return union_obj.owner_decl;
59683293 },
5969 .@"opaque" => {
5970 const opaque_obj = ty.cast(Payload.Opaque).?.data;
5971 return opaque_obj.owner_decl;
5972 },
5973 .atomic_order,
5974 .atomic_rmw_op,
5975 .calling_convention,
5976 .address_space,
5977 .float_mode,
5978 .reduce_op,
5979 .modifier,
5980 .prefetch_options,
5981 .export_options,
5982 .extern_options,
5983 .type_info,
5984 => unreachable, // These need to be resolved earlier.
5985
5986 else => return null,
5987 }
3294 .opaque_type => |opaque_type| opaque_type.decl,
3295 .enum_type => |enum_type| enum_type.decl,
3296 else => null,
3297 };
59883298 }
59893299
5990 /// This enum does not directly correspond to `std.builtin.TypeId` because
5991 /// it has extra enum tags in it, as a way of using less memory. For example,
5992 /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types
5993 /// but with different alignment values, in this data structure they are represented
5994 /// with different enum tags, because the the former requires more payload data than the latter.
5995 /// See `zigTypeTag` for the function that corresponds to `std.builtin.TypeId`.
5996 pub const Tag = enum(usize) {
5997 // The first section of this enum are tags that require no payload.
5998 u1,
5999 u8,
6000 i8,
6001 u16,
6002 i16,
6003 u29,
6004 u32,
6005 i32,
6006 u64,
6007 i64,
6008 u128,
6009 i128,
6010 usize,
6011 isize,
6012 c_char,
6013 c_short,
6014 c_ushort,
6015 c_int,
6016 c_uint,
6017 c_long,
6018 c_ulong,
6019 c_longlong,
6020 c_ulonglong,
6021 c_longdouble,
6022 f16,
6023 f32,
6024 f64,
6025 f80,
6026 f128,
6027 anyopaque,
6028 bool,
6029 void,
6030 type,
6031 anyerror,
6032 comptime_int,
6033 comptime_float,
6034 noreturn,
6035 @"anyframe",
6036 null,
6037 undefined,
6038 enum_literal,
6039 atomic_order,
6040 atomic_rmw_op,
6041 calling_convention,
6042 address_space,
6043 float_mode,
6044 reduce_op,
6045 modifier,
6046 prefetch_options,
6047 export_options,
6048 extern_options,
6049 type_info,
6050 manyptr_u8,
6051 manyptr_const_u8,
6052 manyptr_const_u8_sentinel_0,
6053 fn_noreturn_no_args,
6054 fn_void_no_args,
6055 fn_naked_noreturn_no_args,
6056 fn_ccc_void_no_args,
6057 single_const_pointer_to_comptime_int,
6058 const_slice_u8,
6059 const_slice_u8_sentinel_0,
6060 anyerror_void_error_union,
6061 generic_poison,
6062 /// Same as `empty_struct` except it has an empty namespace.
6063 empty_struct_literal,
6064 /// This is a special value that tracks a set of types that have been stored
6065 /// to an inferred allocation. It does not support most of the normal type queries.
6066 /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc.
6067 inferred_alloc_mut,
6068 /// Same as `inferred_alloc_mut` but the local is `var` not `const`.
6069 inferred_alloc_const, // See last_no_payload_tag below.
6070 // After this, the tag requires a payload.
6071
6072 array_u8,
6073 array_u8_sentinel_0,
6074 array,
6075 array_sentinel,
6076 vector,
6077 /// Possible Value tags for this: @"struct"
6078 tuple,
6079 /// Possible Value tags for this: @"struct"
6080 anon_struct,
6081 pointer,
6082 single_const_pointer,
6083 single_mut_pointer,
6084 many_const_pointer,
6085 many_mut_pointer,
6086 c_const_pointer,
6087 c_mut_pointer,
6088 const_slice,
6089 mut_slice,
6090 int_signed,
6091 int_unsigned,
6092 function,
6093 optional,
6094 optional_single_mut_pointer,
6095 optional_single_const_pointer,
6096 error_union,
6097 anyframe_T,
6098 error_set,
6099 error_set_single,
6100 /// The type is the inferred error set of a specific function.
6101 error_set_inferred,
6102 error_set_merged,
6103 empty_struct,
6104 @"opaque",
6105 @"struct",
6106 @"union",
6107 union_safety_tagged,
6108 union_tagged,
6109 enum_simple,
6110 enum_numbered,
6111 enum_full,
6112 enum_nonexhaustive,
6113
6114 pub const last_no_payload_tag = Tag.inferred_alloc_const;
6115 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
6116
6117 pub fn Type(comptime t: Tag) type {
6118 // Keep in sync with tools/stage2_pretty_printers_common.py
6119 return switch (t) {
6120 .u1,
6121 .u8,
6122 .i8,
6123 .u16,
6124 .i16,
6125 .u29,
6126 .u32,
6127 .i32,
6128 .u64,
6129 .i64,
6130 .u128,
6131 .i128,
6132 .usize,
6133 .isize,
6134 .c_char,
6135 .c_short,
6136 .c_ushort,
6137 .c_int,
6138 .c_uint,
6139 .c_long,
6140 .c_ulong,
6141 .c_longlong,
6142 .c_ulonglong,
6143 .c_longdouble,
6144 .f16,
6145 .f32,
6146 .f64,
6147 .f80,
6148 .f128,
6149 .anyopaque,
6150 .bool,
6151 .void,
6152 .type,
6153 .anyerror,
6154 .comptime_int,
6155 .comptime_float,
6156 .noreturn,
6157 .enum_literal,
6158 .null,
6159 .undefined,
6160 .fn_noreturn_no_args,
6161 .fn_void_no_args,
6162 .fn_naked_noreturn_no_args,
6163 .fn_ccc_void_no_args,
6164 .single_const_pointer_to_comptime_int,
6165 .anyerror_void_error_union,
6166 .const_slice_u8,
6167 .const_slice_u8_sentinel_0,
6168 .generic_poison,
6169 .inferred_alloc_const,
6170 .inferred_alloc_mut,
6171 .empty_struct_literal,
6172 .manyptr_u8,
6173 .manyptr_const_u8,
6174 .manyptr_const_u8_sentinel_0,
6175 .atomic_order,
6176 .atomic_rmw_op,
6177 .calling_convention,
6178 .address_space,
6179 .float_mode,
6180 .reduce_op,
6181 .modifier,
6182 .prefetch_options,
6183 .export_options,
6184 .extern_options,
6185 .type_info,
6186 .@"anyframe",
6187 => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"),
6188
6189 .array_u8,
6190 .array_u8_sentinel_0,
6191 => Payload.Len,
6192
6193 .single_const_pointer,
6194 .single_mut_pointer,
6195 .many_const_pointer,
6196 .many_mut_pointer,
6197 .c_const_pointer,
6198 .c_mut_pointer,
6199 .const_slice,
6200 .mut_slice,
6201 .optional,
6202 .optional_single_mut_pointer,
6203 .optional_single_const_pointer,
6204 .anyframe_T,
6205 => Payload.ElemType,
6206
6207 .int_signed,
6208 .int_unsigned,
6209 => Payload.Bits,
6210
6211 .error_set => Payload.ErrorSet,
6212 .error_set_inferred => Payload.ErrorSetInferred,
6213 .error_set_merged => Payload.ErrorSetMerged,
6214
6215 .array, .vector => Payload.Array,
6216 .array_sentinel => Payload.ArraySentinel,
6217 .pointer => Payload.Pointer,
6218 .function => Payload.Function,
6219 .error_union => Payload.ErrorUnion,
6220 .error_set_single => Payload.Name,
6221 .@"opaque" => Payload.Opaque,
6222 .@"struct" => Payload.Struct,
6223 .@"union", .union_safety_tagged, .union_tagged => Payload.Union,
6224 .enum_full, .enum_nonexhaustive => Payload.EnumFull,
6225 .enum_simple => Payload.EnumSimple,
6226 .enum_numbered => Payload.EnumNumbered,
6227 .empty_struct => Payload.ContainerScope,
6228 .tuple => Payload.Tuple,
6229 .anon_struct => Payload.AnonStruct,
6230 };
6231 }
6232
6233 pub fn init(comptime t: Tag) file_struct.Type {
6234 comptime std.debug.assert(@enumToInt(t) < Tag.no_payload_count);
6235 return .{ .tag_if_small_enough = t };
6236 }
6237
6238 pub fn create(comptime t: Tag, ally: Allocator, data: Data(t)) error{OutOfMemory}!file_struct.Type {
6239 const p = try ally.create(t.Type());
6240 p.* = .{
6241 .base = .{ .tag = t },
6242 .data = data,
6243 };
6244 return file_struct.Type{ .ptr_otherwise = &p.base };
6245 }
6246
6247 pub fn Data(comptime t: Tag) type {
6248 return std.meta.fieldInfo(t.Type(), .data).type;
6249 }
6250 };
6251
6252 pub fn isTuple(ty: Type) bool {
6253 return switch (ty.tag()) {
6254 .tuple, .empty_struct_literal => true,
6255 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
6256 else => false,
6257 };
3300 pub fn isGenericPoison(ty: Type) bool {
3301 return ty.toIntern() == .generic_poison_type;
62583302 }
62593303
6260 pub fn isAnonStruct(ty: Type) bool {
6261 return switch (ty.tag()) {
6262 .anon_struct, .empty_struct_literal => true,
3304 pub fn isTuple(ty: Type, mod: *Module) bool {
3305 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3306 .struct_type => |struct_type| {
3307 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
3308 return struct_obj.is_tuple;
3309 },
3310 .anon_struct_type => |anon_struct| anon_struct.names.len == 0,
62633311 else => false,
62643312 };
62653313 }
62663314
6267 pub fn isTupleOrAnonStruct(ty: Type) bool {
6268 return switch (ty.tag()) {
6269 .tuple, .empty_struct_literal, .anon_struct => true,
6270 .@"struct" => ty.castTag(.@"struct").?.data.is_tuple,
3315 pub fn isAnonStruct(ty: Type, mod: *Module) bool {
3316 if (ty.toIntern() == .empty_struct_type) return true;
3317 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3318 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len > 0,
62713319 else => false,
62723320 };
62733321 }
62743322
6275 pub fn isSimpleTuple(ty: Type) bool {
6276 return switch (ty.tag()) {
6277 .tuple, .empty_struct_literal => true,
3323 pub fn isTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3324 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3325 .struct_type => |struct_type| {
3326 const struct_obj = mod.structPtrUnwrap(struct_type.index) orelse return false;
3327 return struct_obj.is_tuple;
3328 },
3329 .anon_struct_type => true,
62783330 else => false,
62793331 };
62803332 }
62813333
6282 pub fn isSimpleTupleOrAnonStruct(ty: Type) bool {
6283 return switch (ty.tag()) {
6284 .tuple, .empty_struct_literal, .anon_struct => true,
3334 pub fn isSimpleTuple(ty: Type, mod: *Module) bool {
3335 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3336 .anon_struct_type => |anon_struct_type| anon_struct_type.names.len == 0,
62853337 else => false,
62863338 };
62873339 }
62883340
6289 // Only allowed for simple tuple types
6290 pub fn tupleFields(ty: Type) Payload.Tuple.Data {
6291 return switch (ty.tag()) {
6292 .tuple => ty.castTag(.tuple).?.data,
6293 .anon_struct => .{
6294 .types = ty.castTag(.anon_struct).?.data.types,
6295 .values = ty.castTag(.anon_struct).?.data.values,
6296 },
6297 .empty_struct_literal => .{ .types = &.{}, .values = &.{} },
6298 else => unreachable,
3341 pub fn isSimpleTupleOrAnonStruct(ty: Type, mod: *Module) bool {
3342 return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
3343 .anon_struct_type => true,
3344 else => false,
62993345 };
63003346 }
63013347
6302 /// The sub-types are named after what fields they contain.
63033348 pub const Payload = struct {
6304 tag: Tag,
6305
6306 pub const Len = struct {
6307 base: Payload,
6308 data: u64,
6309 };
6310
6311 pub const Array = struct {
6312 base: Payload,
6313 data: struct {
6314 len: u64,
6315 elem_type: Type,
6316 },
6317 };
6318
6319 pub const ArraySentinel = struct {
6320 pub const base_tag = Tag.array_sentinel;
6321
6322 base: Payload = Payload{ .tag = base_tag },
6323 data: struct {
6324 len: u64,
6325 sentinel: Value,
6326 elem_type: Type,
6327 },
6328 };
6329
6330 pub const ElemType = struct {
6331 base: Payload,
6332 data: Type,
6333 };
6334
6335 pub const Bits = struct {
6336 base: Payload,
6337 data: u16,
6338 };
6339
6340 pub const Function = struct {
6341 pub const base_tag = Tag.function;
6342
6343 base: Payload = Payload{ .tag = base_tag },
6344 data: Data,
6345
6346 // TODO look into optimizing this memory to take fewer bytes
6347 pub const Data = struct {
6348 param_types: []Type,
6349 comptime_params: [*]bool,
6350 return_type: Type,
6351 /// If zero use default target function code alignment.
6352 alignment: u32,
6353 noalias_bits: u32,
6354 cc: std.builtin.CallingConvention,
6355 is_var_args: bool,
6356 is_generic: bool,
6357 is_noinline: bool,
6358 align_is_generic: bool,
6359 cc_is_generic: bool,
6360 section_is_generic: bool,
6361 addrspace_is_generic: bool,
6362
6363 pub fn paramIsComptime(self: @This(), i: usize) bool {
6364 assert(i < self.param_types.len);
6365 return self.comptime_params[i];
6366 }
6367 };
6368 };
6369
6370 pub const ErrorSet = struct {
6371 pub const base_tag = Tag.error_set;
6372
6373 base: Payload = Payload{ .tag = base_tag },
6374 data: *Module.ErrorSet,
6375 };
6376
6377 pub const ErrorSetMerged = struct {
6378 pub const base_tag = Tag.error_set_merged;
6379
6380 base: Payload = Payload{ .tag = base_tag },
6381 data: Module.ErrorSet.NameMap,
6382 };
6383
6384 pub const ErrorSetInferred = struct {
6385 pub const base_tag = Tag.error_set_inferred;
6386
6387 base: Payload = Payload{ .tag = base_tag },
6388 data: *Module.Fn.InferredErrorSet,
6389 };
6390
3349 /// TODO: remove this data structure since we have `InternPool.Key.PtrType`.
63913350 pub const Pointer = struct {
6392 pub const base_tag = Tag.pointer;
6393
6394 base: Payload = Payload{ .tag = base_tag },
6395 data: Data,
6396
63973351 pub const Data = struct {
63983352 pointee_type: Type,
63993353 sentinel: ?Value = null,
......@@ -6417,145 +3371,103 @@ pub const Type = extern union {
64173371 @"volatile": bool = false,
64183372 size: std.builtin.Type.Pointer.Size = .One,
64193373
6420 pub const VectorIndex = enum(u32) {
6421 none = std.math.maxInt(u32),
6422 runtime = std.math.maxInt(u32) - 1,
6423 _,
6424 };
3374 pub const VectorIndex = InternPool.Key.PtrType.VectorIndex;
64253375
6426 pub fn alignment(data: Data, target: Target) u32 {
3376 pub fn alignment(data: Data, mod: *Module) u32 {
64273377 if (data.@"align" != 0) return data.@"align";
6428 return abiAlignment(data.pointee_type, target);
3378 return abiAlignment(data.pointee_type, mod);
3379 }
3380
3381 pub fn fromKey(p: InternPool.Key.PtrType) Data {
3382 return .{
3383 .pointee_type = p.child.toType(),
3384 .sentinel = if (p.sentinel != .none) p.sentinel.toValue() else null,
3385 .@"align" = @intCast(u32, p.flags.alignment.toByteUnits(0)),
3386 .@"addrspace" = p.flags.address_space,
3387 .bit_offset = p.packed_offset.bit_offset,
3388 .host_size = p.packed_offset.host_size,
3389 .vector_index = p.flags.vector_index,
3390 .@"allowzero" = p.flags.is_allowzero,
3391 .mutable = !p.flags.is_const,
3392 .@"volatile" = p.flags.is_volatile,
3393 .size = p.flags.size,
3394 };
64293395 }
64303396 };
64313397 };
3398 };
64323399
6433 pub const ErrorUnion = struct {
6434 pub const base_tag = Tag.error_union;
6435
6436 base: Payload = Payload{ .tag = base_tag },
6437 data: struct {
6438 error_set: Type,
6439 payload: Type,
6440 },
6441 };
6442
6443 pub const Decl = struct {
6444 base: Payload,
6445 data: *Module.Decl,
6446 };
6447
6448 pub const Name = struct {
6449 base: Payload,
6450 /// memory is owned by `Module`
6451 data: []const u8,
6452 };
6453
6454 /// Mostly used for namespace like structs with zero fields.
6455 /// Most commonly used for files.
6456 pub const ContainerScope = struct {
6457 base: Payload,
6458 data: *Module.Namespace,
6459 };
6460
6461 pub const Opaque = struct {
6462 base: Payload = .{ .tag = .@"opaque" },
6463 data: *Module.Opaque,
6464 };
6465
6466 pub const Struct = struct {
6467 base: Payload = .{ .tag = .@"struct" },
6468 data: *Module.Struct,
6469 };
6470
6471 pub const Tuple = struct {
6472 base: Payload = .{ .tag = .tuple },
6473 data: Data,
6474
6475 pub const Data = struct {
6476 types: []Type,
6477 /// unreachable_value elements are used to indicate runtime-known.
6478 values: []Value,
6479 };
6480 };
6481
6482 pub const AnonStruct = struct {
6483 base: Payload = .{ .tag = .anon_struct },
6484 data: Data,
6485
6486 pub const Data = struct {
6487 names: []const []const u8,
6488 types: []Type,
6489 /// unreachable_value elements are used to indicate runtime-known.
6490 values: []Value,
6491 };
6492 };
6493
6494 pub const Union = struct {
6495 base: Payload,
6496 data: *Module.Union,
6497 };
6498
6499 pub const EnumFull = struct {
6500 base: Payload,
6501 data: *Module.EnumFull,
6502 };
6503
6504 pub const EnumSimple = struct {
6505 base: Payload = .{ .tag = .enum_simple },
6506 data: *Module.EnumSimple,
6507 };
6508
6509 pub const EnumNumbered = struct {
6510 base: Payload = .{ .tag = .enum_numbered },
6511 data: *Module.EnumNumbered,
6512 };
3400 pub const @"u1": Type = .{ .ip_index = .u1_type };
3401 pub const @"u8": Type = .{ .ip_index = .u8_type };
3402 pub const @"u16": Type = .{ .ip_index = .u16_type };
3403 pub const @"u29": Type = .{ .ip_index = .u29_type };
3404 pub const @"u32": Type = .{ .ip_index = .u32_type };
3405 pub const @"u64": Type = .{ .ip_index = .u64_type };
3406 pub const @"u128": Type = .{ .ip_index = .u128_type };
3407
3408 pub const @"i8": Type = .{ .ip_index = .i8_type };
3409 pub const @"i16": Type = .{ .ip_index = .i16_type };
3410 pub const @"i32": Type = .{ .ip_index = .i32_type };
3411 pub const @"i64": Type = .{ .ip_index = .i64_type };
3412 pub const @"i128": Type = .{ .ip_index = .i128_type };
3413
3414 pub const @"f16": Type = .{ .ip_index = .f16_type };
3415 pub const @"f32": Type = .{ .ip_index = .f32_type };
3416 pub const @"f64": Type = .{ .ip_index = .f64_type };
3417 pub const @"f80": Type = .{ .ip_index = .f80_type };
3418 pub const @"f128": Type = .{ .ip_index = .f128_type };
3419
3420 pub const @"bool": Type = .{ .ip_index = .bool_type };
3421 pub const @"usize": Type = .{ .ip_index = .usize_type };
3422 pub const @"isize": Type = .{ .ip_index = .isize_type };
3423 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type };
3424 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type };
3425 pub const @"void": Type = .{ .ip_index = .void_type };
3426 pub const @"type": Type = .{ .ip_index = .type_type };
3427 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type };
3428 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type };
3429 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type };
3430 pub const @"null": Type = .{ .ip_index = .null_type };
3431 pub const @"undefined": Type = .{ .ip_index = .undefined_type };
3432 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type };
3433
3434 pub const @"c_char": Type = .{ .ip_index = .c_char_type };
3435 pub const @"c_short": Type = .{ .ip_index = .c_short_type };
3436 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type };
3437 pub const @"c_int": Type = .{ .ip_index = .c_int_type };
3438 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type };
3439 pub const @"c_long": Type = .{ .ip_index = .c_long_type };
3440 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type };
3441 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type };
3442 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type };
3443 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type };
3444
3445 pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type };
3446 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type };
3447 pub const single_const_pointer_to_comptime_int: Type = .{
3448 .ip_index = .single_const_pointer_to_comptime_int_type,
65133449 };
3450 pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type };
3451 pub const empty_struct_literal: Type = .{ .ip_index = .empty_struct_type };
65143452
6515 pub const @"u1" = initTag(.u1);
6516 pub const @"u8" = initTag(.u8);
6517 pub const @"u16" = initTag(.u16);
6518 pub const @"u29" = initTag(.u29);
6519 pub const @"u32" = initTag(.u32);
6520 pub const @"u64" = initTag(.u64);
6521
6522 pub const @"i32" = initTag(.i32);
6523 pub const @"i64" = initTag(.i64);
6524
6525 pub const @"f16" = initTag(.f16);
6526 pub const @"f32" = initTag(.f32);
6527 pub const @"f64" = initTag(.f64);
6528 pub const @"f80" = initTag(.f80);
6529 pub const @"f128" = initTag(.f128);
6530
6531 pub const @"bool" = initTag(.bool);
6532 pub const @"usize" = initTag(.usize);
6533 pub const @"isize" = initTag(.isize);
6534 pub const @"comptime_int" = initTag(.comptime_int);
6535 pub const @"void" = initTag(.void);
6536 pub const @"type" = initTag(.type);
6537 pub const @"anyerror" = initTag(.anyerror);
6538 pub const @"anyopaque" = initTag(.anyopaque);
6539 pub const @"null" = initTag(.null);
3453 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type };
65403454
65413455 pub const err_int = Type.u16;
65423456
65433457 pub fn ptr(arena: Allocator, mod: *Module, data: Payload.Pointer.Data) !Type {
6544 const target = mod.getTarget();
3458 // TODO: update callsites of this function to directly call mod.ptrType
3459 // and then delete this function.
3460 _ = arena;
65453461
65463462 var d = data;
65473463
6548 if (d.size == .C) {
6549 d.@"allowzero" = true;
6550 }
6551
65523464 // Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
65533465 // type, we change it to 0 here. If this causes an assertion trip because the
65543466 // pointee type needs to be resolved more, that needs to be done before calling
65553467 // this ptr() function.
65563468 if (d.@"align" != 0) canonicalize: {
6557 if (!d.pointee_type.layoutIsResolved()) break :canonicalize;
6558 if (d.@"align" == d.pointee_type.abiAlignment(target)) {
3469 if (!d.pointee_type.layoutIsResolved(mod)) break :canonicalize;
3470 if (d.@"align" == d.pointee_type.abiAlignment(mod)) {
65593471 d.@"align" = 0;
65603472 }
65613473 }
......@@ -6565,57 +3477,29 @@ pub const Type = extern union {
65653477 // needs to be resolved before calling this ptr() function.
65663478 if (d.host_size != 0) {
65673479 assert(d.bit_offset < d.host_size * 8);
6568 if (d.host_size * 8 == d.pointee_type.bitSize(target)) {
3480 if (d.host_size * 8 == d.pointee_type.bitSize(mod)) {
65693481 assert(d.bit_offset == 0);
65703482 d.host_size = 0;
65713483 }
65723484 }
65733485
6574 if (d.@"align" == 0 and d.@"addrspace" == .generic and
6575 d.bit_offset == 0 and d.host_size == 0 and d.vector_index == .none and
6576 !d.@"allowzero" and !d.@"volatile")
6577 {
6578 if (d.sentinel) |sent| {
6579 if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
6580 switch (d.size) {
6581 .Slice => {
6582 if (sent.compareAllWithZero(.eq, mod)) {
6583 return Type.initTag(.const_slice_u8_sentinel_0);
6584 }
6585 },
6586 .Many => {
6587 if (sent.compareAllWithZero(.eq, mod)) {
6588 return Type.initTag(.manyptr_const_u8_sentinel_0);
6589 }
6590 },
6591 else => {},
6592 }
6593 }
6594 } else if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
6595 switch (d.size) {
6596 .Slice => return Type.initTag(.const_slice_u8),
6597 .Many => return Type.initTag(.manyptr_const_u8),
6598 else => {},
6599 }
6600 } else {
6601 const T = Type.Tag;
6602 const type_payload = try arena.create(Type.Payload.ElemType);
6603 type_payload.* = .{
6604 .base = .{
6605 .tag = switch (d.size) {
6606 .One => if (d.mutable) T.single_mut_pointer else T.single_const_pointer,
6607 .Many => if (d.mutable) T.many_mut_pointer else T.many_const_pointer,
6608 .C => if (d.mutable) T.c_mut_pointer else T.c_const_pointer,
6609 .Slice => if (d.mutable) T.mut_slice else T.const_slice,
6610 },
6611 },
6612 .data = d.pointee_type,
6613 };
6614 return Type.initPayload(&type_payload.base);
6615 }
6616 }
6617
6618 return Type.Tag.pointer.create(arena, d);
3486 return mod.ptrType(.{
3487 .child = d.pointee_type.ip_index,
3488 .sentinel = if (d.sentinel) |s| s.ip_index else .none,
3489 .flags = .{
3490 .alignment = InternPool.Alignment.fromByteUnits(d.@"align"),
3491 .vector_index = d.vector_index,
3492 .size = d.size,
3493 .is_const = !d.mutable,
3494 .is_volatile = d.@"volatile",
3495 .is_allowzero = d.@"allowzero",
3496 .address_space = d.@"addrspace",
3497 },
3498 .packed_offset = .{
3499 .host_size = d.host_size,
3500 .bit_offset = d.bit_offset,
3501 },
3502 });
66193503 }
66203504
66213505 pub fn array(
......@@ -6625,68 +3509,23 @@ pub const Type = extern union {
66253509 elem_type: Type,
66263510 mod: *Module,
66273511 ) Allocator.Error!Type {
6628 if (elem_type.eql(Type.u8, mod)) {
6629 if (sent) |some| {
6630 if (some.eql(Value.zero, elem_type, mod)) {
6631 return Tag.array_u8_sentinel_0.create(arena, len);
6632 }
6633 } else {
6634 return Tag.array_u8.create(arena, len);
6635 }
6636 }
6637
6638 if (sent) |some| {
6639 return Tag.array_sentinel.create(arena, .{
6640 .len = len,
6641 .sentinel = some,
6642 .elem_type = elem_type,
6643 });
6644 }
6645
6646 return Tag.array.create(arena, .{
6647 .len = len,
6648 .elem_type = elem_type,
6649 });
6650 }
3512 // TODO: update callsites of this function to directly call mod.arrayType
3513 // and then delete this function.
3514 _ = arena;
66513515
6652 pub fn vector(arena: Allocator, len: u64, elem_type: Type) Allocator.Error!Type {
6653 return Tag.vector.create(arena, .{
3516 return mod.arrayType(.{
66543517 .len = len,
6655 .elem_type = elem_type,
3518 .child = elem_type.ip_index,
3519 .sentinel = if (sent) |s| s.ip_index else .none,
66563520 });
66573521 }
66583522
6659 pub fn optional(arena: Allocator, child_type: Type) Allocator.Error!Type {
6660 switch (child_type.tag()) {
6661 .single_const_pointer => return Type.Tag.optional_single_const_pointer.create(
6662 arena,
6663 child_type.elemType(),
6664 ),
6665 .single_mut_pointer => return Type.Tag.optional_single_mut_pointer.create(
6666 arena,
6667 child_type.elemType(),
6668 ),
6669 else => return Type.Tag.optional.create(arena, child_type),
6670 }
6671 }
6672
6673 pub fn errorUnion(
6674 arena: Allocator,
6675 error_set: Type,
6676 payload: Type,
6677 mod: *Module,
6678 ) Allocator.Error!Type {
6679 assert(error_set.zigTypeTag() == .ErrorSet);
6680 if (error_set.eql(Type.anyerror, mod) and
6681 payload.eql(Type.void, mod))
6682 {
6683 return Type.initTag(.anyerror_void_error_union);
6684 }
3523 pub fn optional(arena: Allocator, child_type: Type, mod: *Module) Allocator.Error!Type {
3524 // TODO: update callsites of this function to directly call
3525 // mod.optionalType and then delete this function.
3526 _ = arena;
66853527
6686 return Type.Tag.error_union.create(arena, .{
6687 .error_set = error_set,
6688 .payload = payload,
6689 });
3528 return mod.optionalType(child_type.ip_index);
66903529 }
66913530
66923531 pub fn smallestUnsignedBits(max: u64) u16 {
......@@ -6696,113 +3535,7 @@ pub const Type = extern union {
66963535 return @intCast(u16, base + @boolToInt(upper < max));
66973536 }
66983537
6699 pub fn smallestUnsignedInt(arena: Allocator, max: u64) !Type {
6700 const bits = smallestUnsignedBits(max);
6701 return intWithBits(arena, false, bits);
6702 }
6703
6704 pub fn intWithBits(arena: Allocator, sign: bool, bits: u16) !Type {
6705 return if (sign) switch (bits) {
6706 8 => initTag(.i8),
6707 16 => initTag(.i16),
6708 32 => initTag(.i32),
6709 64 => initTag(.i64),
6710 else => return Tag.int_signed.create(arena, bits),
6711 } else switch (bits) {
6712 1 => initTag(.u1),
6713 8 => initTag(.u8),
6714 16 => initTag(.u16),
6715 32 => initTag(.u32),
6716 64 => initTag(.u64),
6717 else => return Tag.int_unsigned.create(arena, bits),
6718 };
6719 }
6720
6721 /// Given a value representing an integer, returns the number of bits necessary to represent
6722 /// this value in an integer. If `sign` is true, returns the number of bits necessary in a
6723 /// twos-complement integer; otherwise in an unsigned integer.
6724 /// Asserts that `val` is not undef. If `val` is negative, asserts that `sign` is true.
6725 pub fn intBitsForValue(target: Target, val: Value, sign: bool) u16 {
6726 assert(!val.isUndef());
6727 switch (val.tag()) {
6728 .int_big_positive => {
6729 const limbs = val.castTag(.int_big_positive).?.data;
6730 const big: std.math.big.int.Const = .{ .limbs = limbs, .positive = true };
6731 return @intCast(u16, big.bitCountAbs() + @boolToInt(sign));
6732 },
6733 .int_big_negative => {
6734 const limbs = val.castTag(.int_big_negative).?.data;
6735 // Zero is still a possibility, in which case unsigned is fine
6736 for (limbs) |limb| {
6737 if (limb != 0) break;
6738 } else return 0; // val == 0
6739 assert(sign);
6740 const big: std.math.big.int.Const = .{ .limbs = limbs, .positive = false };
6741 return @intCast(u16, big.bitCountTwosComp());
6742 },
6743 .int_i64 => {
6744 const x = val.castTag(.int_i64).?.data;
6745 if (x >= 0) return smallestUnsignedBits(@intCast(u64, x));
6746 assert(sign);
6747 return smallestUnsignedBits(@intCast(u64, -x - 1)) + 1;
6748 },
6749 else => {
6750 const x = val.toUnsignedInt(target);
6751 return smallestUnsignedBits(x) + @boolToInt(sign);
6752 },
6753 }
6754 }
6755
6756 /// Returns the smallest possible integer type containing both `min` and `max`. Asserts that neither
6757 /// value is undef.
6758 /// TODO: if #3806 is implemented, this becomes trivial
6759 pub fn intFittingRange(target: Target, arena: Allocator, min: Value, max: Value) !Type {
6760 assert(!min.isUndef());
6761 assert(!max.isUndef());
6762
6763 if (std.debug.runtime_safety) {
6764 assert(Value.order(min, max, target).compare(.lte));
6765 }
6766
6767 const sign = min.orderAgainstZero() == .lt;
6768
6769 const min_val_bits = intBitsForValue(target, min, sign);
6770 const max_val_bits = intBitsForValue(target, max, sign);
6771 const bits = @max(min_val_bits, max_val_bits);
6772
6773 return intWithBits(arena, sign, bits);
6774 }
6775
67763538 /// This is only used for comptime asserts. Bump this number when you make a change
67773539 /// to packed struct layout to find out all the places in the codebase you need to edit!
67783540 pub const packed_struct_layout_version = 2;
6779
6780 /// This function is used in the debugger pretty formatters in tools/ to fetch the
6781 /// Tag to Payload mapping to facilitate fancy debug printing for this type.
6782 fn dbHelper(self: *Type, tag_to_payload_map: *map: {
6783 const tags = @typeInfo(Tag).Enum.fields;
6784 var fields: [tags.len]std.builtin.Type.StructField = undefined;
6785 for (&fields, tags) |*field, t| field.* = .{
6786 .name = t.name,
6787 .type = *if (t.value < Tag.no_payload_count) void else @field(Tag, t.name).Type(),
6788 .default_value = null,
6789 .is_comptime = false,
6790 .alignment = 0,
6791 };
6792 break :map @Type(.{ .Struct = .{
6793 .layout = .Extern,
6794 .fields = &fields,
6795 .decls = &.{},
6796 .is_tuple = false,
6797 } });
6798 }) void {
6799 _ = self;
6800 _ = tag_to_payload_map;
6801 }
6802
6803 comptime {
6804 if (builtin.mode == .Debug) {
6805 _ = &dbHelper;
6806 }
6807 }
68083541};
src/value.zig+2265-3741
......@@ -11,147 +11,27 @@ const Module = @import("Module.zig");
1111const Air = @import("Air.zig");
1212const TypedValue = @import("TypedValue.zig");
1313const Sema = @import("Sema.zig");
14
15/// This is the raw data, with no bookkeeping, no memory awareness,
16/// no de-duplication, and no type system awareness.
17/// It's important for this type to be small.
18/// This union takes advantage of the fact that the first page of memory
19/// is unmapped, giving us 4096 possible enum tags that have no payload.
20pub const Value = extern union {
21 /// If the tag value is less than Tag.no_payload_count, then no pointer
22 /// dereference is needed.
23 tag_if_small_enough: Tag,
24 ptr_otherwise: *Payload,
14const InternPool = @import("InternPool.zig");
15
16pub const Value = struct {
17 /// We are migrating towards using this for every Value object. However, many
18 /// values are still represented the legacy way. This is indicated by using
19 /// InternPool.Index.none.
20 ip_index: InternPool.Index,
21
22 /// This is the raw data, with no bookkeeping, no memory awareness,
23 /// no de-duplication, and no type system awareness.
24 /// This union takes advantage of the fact that the first page of memory
25 /// is unmapped, giving us 4096 possible enum tags that have no payload.
26 legacy: extern union {
27 ptr_otherwise: *Payload,
28 },
2529
2630 // Keep in sync with tools/stage2_pretty_printers_common.py
2731 pub const Tag = enum(usize) {
2832 // The first section of this enum are tags that require no payload.
29 u1_type,
30 u8_type,
31 i8_type,
32 u16_type,
33 i16_type,
34 u29_type,
35 u32_type,
36 i32_type,
37 u64_type,
38 i64_type,
39 u128_type,
40 i128_type,
41 usize_type,
42 isize_type,
43 c_char_type,
44 c_short_type,
45 c_ushort_type,
46 c_int_type,
47 c_uint_type,
48 c_long_type,
49 c_ulong_type,
50 c_longlong_type,
51 c_ulonglong_type,
52 c_longdouble_type,
53 f16_type,
54 f32_type,
55 f64_type,
56 f80_type,
57 f128_type,
58 anyopaque_type,
59 bool_type,
60 void_type,
61 type_type,
62 anyerror_type,
63 comptime_int_type,
64 comptime_float_type,
65 noreturn_type,
66 anyframe_type,
67 null_type,
68 undefined_type,
69 enum_literal_type,
70 atomic_order_type,
71 atomic_rmw_op_type,
72 calling_convention_type,
73 address_space_type,
74 float_mode_type,
75 reduce_op_type,
76 modifier_type,
77 prefetch_options_type,
78 export_options_type,
79 extern_options_type,
80 type_info_type,
81 manyptr_u8_type,
82 manyptr_const_u8_type,
83 manyptr_const_u8_sentinel_0_type,
84 fn_noreturn_no_args_type,
85 fn_void_no_args_type,
86 fn_naked_noreturn_no_args_type,
87 fn_ccc_void_no_args_type,
88 single_const_pointer_to_comptime_int_type,
89 const_slice_u8_type,
90 const_slice_u8_sentinel_0_type,
91 anyerror_void_error_union_type,
92 generic_poison_type,
93
94 undef,
95 zero,
96 one,
97 void_value,
98 unreachable_value,
99 /// The only possible value for a particular type, which is stored externally.
100 the_only_possible_value,
101 null_value,
102 bool_true,
103 bool_false,
104 generic_poison,
105
106 empty_struct_value,
107 empty_array, // See last_no_payload_tag below.
10833 // After this, the tag requires a payload.
10934
110 ty,
111 int_type,
112 int_u64,
113 int_i64,
114 int_big_positive,
115 int_big_negative,
116 function,
117 extern_fn,
118 variable,
119 /// A wrapper for values which are comptime-known but should
120 /// semantically be runtime-known.
121 runtime_value,
122 /// Represents a pointer to a Decl.
123 /// When machine codegen backend sees this, it must set the Decl's `alive` field to true.
124 decl_ref,
125 /// Pointer to a Decl, but allows comptime code to mutate the Decl's Value.
126 /// This Tag will never be seen by machine codegen backends. It is changed into a
127 /// `decl_ref` when a comptime variable goes out of scope.
128 decl_ref_mut,
129 /// Behaves like `decl_ref_mut` but validates that the stored value matches the field value.
130 comptime_field_ptr,
131 /// Pointer to a specific element of an array, vector or slice.
132 elem_ptr,
133 /// Pointer to a specific field of a struct or union.
134 field_ptr,
135 /// A slice of u8 whose memory is managed externally.
136 bytes,
137 /// Similar to bytes however it stores an index relative to `Module.string_literal_bytes`.
138 str_lit,
139 /// This value is repeated some number of times. The amount of times to repeat
140 /// is stored externally.
141 repeated,
142 /// An array with length 0 but it has a sentinel.
143 empty_array_sentinel,
144 /// Pointer and length as sub `Value` objects.
145 slice,
146 float_16,
147 float_32,
148 float_64,
149 float_80,
150 float_128,
151 enum_literal,
152 /// A specific enum tag, indicated by the field index (declaration order).
153 enum_field_index,
154 @"error",
15535 /// When the type is error union:
15636 /// * If the tag is `.@"error"`, the error union is an error.
15737 /// * If the tag is `.eu_payload`, the error union is a payload.
......@@ -159,8 +39,6 @@ pub const Value = extern union {
15939 /// is non-error, but the inner error union is an error, is represented as
16040 /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`.
16141 eu_payload,
162 /// A pointer to the payload of an error union, based on a pointer to an error union.
163 eu_payload_ptr,
16442 /// When the type is optional:
16543 /// * If the tag is `.null_value`, the optional is null.
16644 /// * If the tag is `.opt_payload`, the optional is a payload.
......@@ -168,8 +46,13 @@ pub const Value = extern union {
16846 /// is non-null, but the inner optional is null, is represented as
16947 /// a tag of `.opt_payload`, with a sub-tag of `.null_value`.
17048 opt_payload,
171 /// A pointer to the payload of an optional, based on a pointer to an optional.
172 opt_payload_ptr,
49 /// Pointer and length as sub `Value` objects.
50 slice,
51 /// A slice of u8 whose memory is managed externally.
52 bytes,
53 /// This value is repeated some number of times. The amount of times to repeat
54 /// is stored externally.
55 repeated,
17356 /// An instance of a struct, array, or vector.
17457 /// Each element/field stored as a `Value`.
17558 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored,
......@@ -177,152 +60,17 @@ pub const Value = extern union {
17760 aggregate,
17861 /// An instance of a union.
17962 @"union",
180 /// This is a special value that tracks a set of types that have been stored
181 /// to an inferred allocation. It does not support any of the normal value queries.
182 inferred_alloc,
183 /// Used to coordinate alloc_inferred, store_to_inferred_ptr, and resolve_inferred_alloc
184 /// instructions for comptime code.
185 inferred_alloc_comptime,
186 /// The ABI alignment of the payload type.
187 lazy_align,
188 /// The ABI size of the payload type.
189 lazy_size,
190
191 pub const last_no_payload_tag = Tag.empty_array;
192 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
19363
19464 pub fn Type(comptime t: Tag) type {
19565 return switch (t) {
196 .u1_type,
197 .u8_type,
198 .i8_type,
199 .u16_type,
200 .i16_type,
201 .u29_type,
202 .u32_type,
203 .i32_type,
204 .u64_type,
205 .i64_type,
206 .u128_type,
207 .i128_type,
208 .usize_type,
209 .isize_type,
210 .c_char_type,
211 .c_short_type,
212 .c_ushort_type,
213 .c_int_type,
214 .c_uint_type,
215 .c_long_type,
216 .c_ulong_type,
217 .c_longlong_type,
218 .c_ulonglong_type,
219 .c_longdouble_type,
220 .f16_type,
221 .f32_type,
222 .f64_type,
223 .f80_type,
224 .f128_type,
225 .anyopaque_type,
226 .bool_type,
227 .void_type,
228 .type_type,
229 .anyerror_type,
230 .comptime_int_type,
231 .comptime_float_type,
232 .noreturn_type,
233 .null_type,
234 .undefined_type,
235 .fn_noreturn_no_args_type,
236 .fn_void_no_args_type,
237 .fn_naked_noreturn_no_args_type,
238 .fn_ccc_void_no_args_type,
239 .single_const_pointer_to_comptime_int_type,
240 .anyframe_type,
241 .const_slice_u8_type,
242 .const_slice_u8_sentinel_0_type,
243 .anyerror_void_error_union_type,
244 .generic_poison_type,
245 .enum_literal_type,
246 .undef,
247 .zero,
248 .one,
249 .void_value,
250 .unreachable_value,
251 .the_only_possible_value,
252 .empty_struct_value,
253 .empty_array,
254 .null_value,
255 .bool_true,
256 .bool_false,
257 .manyptr_u8_type,
258 .manyptr_const_u8_type,
259 .manyptr_const_u8_sentinel_0_type,
260 .atomic_order_type,
261 .atomic_rmw_op_type,
262 .calling_convention_type,
263 .address_space_type,
264 .float_mode_type,
265 .reduce_op_type,
266 .modifier_type,
267 .prefetch_options_type,
268 .export_options_type,
269 .extern_options_type,
270 .type_info_type,
271 .generic_poison,
272 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
273
274 .int_big_positive,
275 .int_big_negative,
276 => Payload.BigInt,
277
278 .extern_fn => Payload.ExternFn,
279
280 .decl_ref => Payload.Decl,
281
282 .repeated,
28366 .eu_payload,
28467 .opt_payload,
285 .empty_array_sentinel,
286 .runtime_value,
68 .repeated,
28769 => Payload.SubValue,
288
289 .eu_payload_ptr,
290 .opt_payload_ptr,
291 => Payload.PayloadPtr,
292
293 .bytes,
294 .enum_literal,
295 => Payload.Bytes,
296
297 .str_lit => Payload.StrLit,
29870 .slice => Payload.Slice,
299
300 .enum_field_index => Payload.U32,
301
302 .ty,
303 .lazy_align,
304 .lazy_size,
305 => Payload.Ty,
306
307 .int_type => Payload.IntType,
308 .int_u64 => Payload.U64,
309 .int_i64 => Payload.I64,
310 .function => Payload.Function,
311 .variable => Payload.Variable,
312 .decl_ref_mut => Payload.DeclRefMut,
313 .elem_ptr => Payload.ElemPtr,
314 .field_ptr => Payload.FieldPtr,
315 .float_16 => Payload.Float_16,
316 .float_32 => Payload.Float_32,
317 .float_64 => Payload.Float_64,
318 .float_80 => Payload.Float_80,
319 .float_128 => Payload.Float_128,
320 .@"error" => Payload.Error,
321 .inferred_alloc => Payload.InferredAlloc,
322 .inferred_alloc_comptime => Payload.InferredAllocComptime,
71 .bytes => Payload.Bytes,
32372 .aggregate => Payload.Aggregate,
32473 .@"union" => Payload.Union,
325 .comptime_field_ptr => Payload.ComptimeFieldPtr,
32674 };
32775 }
32876
......@@ -332,7 +80,10 @@ pub const Value = extern union {
33280 .base = .{ .tag = t },
33381 .data = data,
33482 };
335 return Value{ .ptr_otherwise = &ptr.base };
83 return Value{
84 .ip_index = .none,
85 .legacy = .{ .ptr_otherwise = &ptr.base },
86 };
33687 }
33788
33889 pub fn Data(comptime t: Tag) type {
......@@ -340,39 +91,31 @@ pub const Value = extern union {
34091 }
34192 };
34293
343 pub fn initTag(small_tag: Tag) Value {
344 assert(@enumToInt(small_tag) < Tag.no_payload_count);
345 return .{ .tag_if_small_enough = small_tag };
346 }
347
34894 pub fn initPayload(payload: *Payload) Value {
349 assert(@enumToInt(payload.tag) >= Tag.no_payload_count);
350 return .{ .ptr_otherwise = payload };
95 return Value{
96 .ip_index = .none,
97 .legacy = .{ .ptr_otherwise = payload },
98 };
35199 }
352100
353101 pub fn tag(self: Value) Tag {
354 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
355 return self.tag_if_small_enough;
356 } else {
357 return self.ptr_otherwise.tag;
358 }
102 assert(self.ip_index == .none);
103 return self.legacy.ptr_otherwise.tag;
359104 }
360105
361106 /// Prefer `castTag` to this.
362107 pub fn cast(self: Value, comptime T: type) ?*T {
108 if (self.ip_index != .none) {
109 return null;
110 }
363111 if (@hasField(T, "base_tag")) {
364112 return self.castTag(T.base_tag);
365113 }
366 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
367 return null;
368 }
369114 inline for (@typeInfo(Tag).Enum.fields) |field| {
370 if (field.value < Tag.no_payload_count)
371 continue;
372115 const t = @intToEnum(Tag, field.value);
373 if (self.ptr_otherwise.tag == t) {
116 if (self.legacy.ptr_otherwise.tag == t) {
374117 if (T == t.Type()) {
375 return @fieldParentPtr(T, "base", self.ptr_otherwise);
118 return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise);
376119 }
377120 return null;
378121 }
......@@ -381,11 +124,10 @@ pub const Value = extern union {
381124 }
382125
383126 pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() {
384 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count)
385 return null;
127 if (self.ip_index != .none) return null;
386128
387 if (self.ptr_otherwise.tag == t)
388 return @fieldParentPtr(t.Type(), "base", self.ptr_otherwise);
129 if (self.legacy.ptr_otherwise.tag == t)
130 return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise);
389131
390132 return null;
391133 }
......@@ -393,165 +135,10 @@ pub const Value = extern union {
393135 /// It's intentional that this function is not passed a corresponding Type, so that
394136 /// a Value can be copied from a Sema to a Decl prior to resolving struct/union field types.
395137 pub fn copy(self: Value, arena: Allocator) error{OutOfMemory}!Value {
396 if (@enumToInt(self.tag_if_small_enough) < Tag.no_payload_count) {
397 return Value{ .tag_if_small_enough = self.tag_if_small_enough };
398 } else switch (self.ptr_otherwise.tag) {
399 .u1_type,
400 .u8_type,
401 .i8_type,
402 .u16_type,
403 .i16_type,
404 .u29_type,
405 .u32_type,
406 .i32_type,
407 .u64_type,
408 .i64_type,
409 .u128_type,
410 .i128_type,
411 .usize_type,
412 .isize_type,
413 .c_char_type,
414 .c_short_type,
415 .c_ushort_type,
416 .c_int_type,
417 .c_uint_type,
418 .c_long_type,
419 .c_ulong_type,
420 .c_longlong_type,
421 .c_ulonglong_type,
422 .c_longdouble_type,
423 .f16_type,
424 .f32_type,
425 .f64_type,
426 .f80_type,
427 .f128_type,
428 .anyopaque_type,
429 .bool_type,
430 .void_type,
431 .type_type,
432 .anyerror_type,
433 .comptime_int_type,
434 .comptime_float_type,
435 .noreturn_type,
436 .null_type,
437 .undefined_type,
438 .fn_noreturn_no_args_type,
439 .fn_void_no_args_type,
440 .fn_naked_noreturn_no_args_type,
441 .fn_ccc_void_no_args_type,
442 .single_const_pointer_to_comptime_int_type,
443 .anyframe_type,
444 .const_slice_u8_type,
445 .const_slice_u8_sentinel_0_type,
446 .anyerror_void_error_union_type,
447 .generic_poison_type,
448 .enum_literal_type,
449 .undef,
450 .zero,
451 .one,
452 .void_value,
453 .unreachable_value,
454 .the_only_possible_value,
455 .empty_array,
456 .null_value,
457 .bool_true,
458 .bool_false,
459 .empty_struct_value,
460 .manyptr_u8_type,
461 .manyptr_const_u8_type,
462 .manyptr_const_u8_sentinel_0_type,
463 .atomic_order_type,
464 .atomic_rmw_op_type,
465 .calling_convention_type,
466 .address_space_type,
467 .float_mode_type,
468 .reduce_op_type,
469 .modifier_type,
470 .prefetch_options_type,
471 .export_options_type,
472 .extern_options_type,
473 .type_info_type,
474 .generic_poison,
475 => unreachable,
476
477 .ty, .lazy_align, .lazy_size => {
478 const payload = self.cast(Payload.Ty).?;
479 const new_payload = try arena.create(Payload.Ty);
480 new_payload.* = .{
481 .base = payload.base,
482 .data = try payload.data.copy(arena),
483 };
484 return Value{ .ptr_otherwise = &new_payload.base };
485 },
486 .int_type => return self.copyPayloadShallow(arena, Payload.IntType),
487 .int_u64 => return self.copyPayloadShallow(arena, Payload.U64),
488 .int_i64 => return self.copyPayloadShallow(arena, Payload.I64),
489 .int_big_positive, .int_big_negative => {
490 const old_payload = self.cast(Payload.BigInt).?;
491 const new_payload = try arena.create(Payload.BigInt);
492 new_payload.* = .{
493 .base = .{ .tag = self.ptr_otherwise.tag },
494 .data = try arena.dupe(std.math.big.Limb, old_payload.data),
495 };
496 return Value{ .ptr_otherwise = &new_payload.base };
497 },
498 .function => return self.copyPayloadShallow(arena, Payload.Function),
499 .extern_fn => return self.copyPayloadShallow(arena, Payload.ExternFn),
500 .variable => return self.copyPayloadShallow(arena, Payload.Variable),
501 .decl_ref => return self.copyPayloadShallow(arena, Payload.Decl),
502 .decl_ref_mut => return self.copyPayloadShallow(arena, Payload.DeclRefMut),
503 .eu_payload_ptr,
504 .opt_payload_ptr,
505 => {
506 const payload = self.cast(Payload.PayloadPtr).?;
507 const new_payload = try arena.create(Payload.PayloadPtr);
508 new_payload.* = .{
509 .base = payload.base,
510 .data = .{
511 .container_ptr = try payload.data.container_ptr.copy(arena),
512 .container_ty = try payload.data.container_ty.copy(arena),
513 },
514 };
515 return Value{ .ptr_otherwise = &new_payload.base };
516 },
517 .comptime_field_ptr => {
518 const payload = self.cast(Payload.ComptimeFieldPtr).?;
519 const new_payload = try arena.create(Payload.ComptimeFieldPtr);
520 new_payload.* = .{
521 .base = payload.base,
522 .data = .{
523 .field_val = try payload.data.field_val.copy(arena),
524 .field_ty = try payload.data.field_ty.copy(arena),
525 },
526 };
527 return Value{ .ptr_otherwise = &new_payload.base };
528 },
529 .elem_ptr => {
530 const payload = self.castTag(.elem_ptr).?;
531 const new_payload = try arena.create(Payload.ElemPtr);
532 new_payload.* = .{
533 .base = payload.base,
534 .data = .{
535 .array_ptr = try payload.data.array_ptr.copy(arena),
536 .elem_ty = try payload.data.elem_ty.copy(arena),
537 .index = payload.data.index,
538 },
539 };
540 return Value{ .ptr_otherwise = &new_payload.base };
541 },
542 .field_ptr => {
543 const payload = self.castTag(.field_ptr).?;
544 const new_payload = try arena.create(Payload.FieldPtr);
545 new_payload.* = .{
546 .base = payload.base,
547 .data = .{
548 .container_ptr = try payload.data.container_ptr.copy(arena),
549 .container_ty = try payload.data.container_ty.copy(arena),
550 .field_index = payload.data.field_index,
551 },
552 };
553 return Value{ .ptr_otherwise = &new_payload.base };
554 },
138 if (self.ip_index != .none) {
139 return Value{ .ip_index = self.ip_index, .legacy = undefined };
140 }
141 switch (self.legacy.ptr_otherwise.tag) {
555142 .bytes => {
556143 const bytes = self.castTag(.bytes).?.data;
557144 const new_payload = try arena.create(Payload.Bytes);
......@@ -559,14 +146,14 @@ pub const Value = extern union {
559146 .base = .{ .tag = .bytes },
560147 .data = try arena.dupe(u8, bytes),
561148 };
562 return Value{ .ptr_otherwise = &new_payload.base };
149 return Value{
150 .ip_index = .none,
151 .legacy = .{ .ptr_otherwise = &new_payload.base },
152 };
563153 },
564 .str_lit => return self.copyPayloadShallow(arena, Payload.StrLit),
565 .repeated,
566154 .eu_payload,
567155 .opt_payload,
568 .empty_array_sentinel,
569 .runtime_value,
156 .repeated,
570157 => {
571158 const payload = self.cast(Payload.SubValue).?;
572159 const new_payload = try arena.create(Payload.SubValue);
......@@ -574,7 +161,10 @@ pub const Value = extern union {
574161 .base = payload.base,
575162 .data = try payload.data.copy(arena),
576163 };
577 return Value{ .ptr_otherwise = &new_payload.base };
164 return Value{
165 .ip_index = .none,
166 .legacy = .{ .ptr_otherwise = &new_payload.base },
167 };
578168 },
579169 .slice => {
580170 const payload = self.castTag(.slice).?;
......@@ -586,25 +176,11 @@ pub const Value = extern union {
586176 .len = try payload.data.len.copy(arena),
587177 },
588178 };
589 return Value{ .ptr_otherwise = &new_payload.base };
590 },
591 .float_16 => return self.copyPayloadShallow(arena, Payload.Float_16),
592 .float_32 => return self.copyPayloadShallow(arena, Payload.Float_32),
593 .float_64 => return self.copyPayloadShallow(arena, Payload.Float_64),
594 .float_80 => return self.copyPayloadShallow(arena, Payload.Float_80),
595 .float_128 => return self.copyPayloadShallow(arena, Payload.Float_128),
596 .enum_literal => {
597 const payload = self.castTag(.enum_literal).?;
598 const new_payload = try arena.create(Payload.Bytes);
599 new_payload.* = .{
600 .base = payload.base,
601 .data = try arena.dupe(u8, payload.data),
179 return Value{
180 .ip_index = .none,
181 .legacy = .{ .ptr_otherwise = &new_payload.base },
602182 };
603 return Value{ .ptr_otherwise = &new_payload.base };
604183 },
605 .enum_field_index => return self.copyPayloadShallow(arena, Payload.U32),
606 .@"error" => return self.copyPayloadShallow(arena, Payload.Error),
607
608184 .aggregate => {
609185 const payload = self.castTag(.aggregate).?;
610186 const new_payload = try arena.create(Payload.Aggregate);
......@@ -615,9 +191,11 @@ pub const Value = extern union {
615191 for (new_payload.data, 0..) |*elem, i| {
616192 elem.* = try payload.data[i].copy(arena);
617193 }
618 return Value{ .ptr_otherwise = &new_payload.base };
194 return Value{
195 .ip_index = .none,
196 .legacy = .{ .ptr_otherwise = &new_payload.base },
197 };
619198 },
620
621199 .@"union" => {
622200 const tag_and_val = self.castTag(.@"union").?.data;
623201 const new_payload = try arena.create(Payload.Union);
......@@ -628,11 +206,11 @@ pub const Value = extern union {
628206 .val = try tag_and_val.val.copy(arena),
629207 },
630208 };
631 return Value{ .ptr_otherwise = &new_payload.base };
209 return Value{
210 .ip_index = .none,
211 .legacy = .{ .ptr_otherwise = &new_payload.base },
212 };
632213 },
633
634 .inferred_alloc => unreachable,
635 .inferred_alloc_comptime => unreachable,
636214 }
637215 }
638216
......@@ -640,7 +218,10 @@ pub const Value = extern union {
640218 const payload = self.cast(T).?;
641219 const new_payload = try arena.create(T);
642220 new_payload.* = payload.*;
643 return Value{ .ptr_otherwise = &new_payload.base };
221 return Value{
222 .ip_index = .none,
223 .legacy = .{ .ptr_otherwise = &new_payload.base },
224 };
644225 }
645226
646227 pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
......@@ -656,181 +237,36 @@ pub const Value = extern union {
656237 pub fn dump(
657238 start_val: Value,
658239 comptime fmt: []const u8,
659 options: std.fmt.FormatOptions,
240 _: std.fmt.FormatOptions,
660241 out_stream: anytype,
661242 ) !void {
662243 comptime assert(fmt.len == 0);
244 if (start_val.ip_index != .none) {
245 try out_stream.print("(interned: {})", .{start_val.toIntern()});
246 return;
247 }
663248 var val = start_val;
664249 while (true) switch (val.tag()) {
665 .u1_type => return out_stream.writeAll("u1"),
666 .u8_type => return out_stream.writeAll("u8"),
667 .i8_type => return out_stream.writeAll("i8"),
668 .u16_type => return out_stream.writeAll("u16"),
669 .u29_type => return out_stream.writeAll("u29"),
670 .i16_type => return out_stream.writeAll("i16"),
671 .u32_type => return out_stream.writeAll("u32"),
672 .i32_type => return out_stream.writeAll("i32"),
673 .u64_type => return out_stream.writeAll("u64"),
674 .i64_type => return out_stream.writeAll("i64"),
675 .u128_type => return out_stream.writeAll("u128"),
676 .i128_type => return out_stream.writeAll("i128"),
677 .isize_type => return out_stream.writeAll("isize"),
678 .usize_type => return out_stream.writeAll("usize"),
679 .c_char_type => return out_stream.writeAll("c_char"),
680 .c_short_type => return out_stream.writeAll("c_short"),
681 .c_ushort_type => return out_stream.writeAll("c_ushort"),
682 .c_int_type => return out_stream.writeAll("c_int"),
683 .c_uint_type => return out_stream.writeAll("c_uint"),
684 .c_long_type => return out_stream.writeAll("c_long"),
685 .c_ulong_type => return out_stream.writeAll("c_ulong"),
686 .c_longlong_type => return out_stream.writeAll("c_longlong"),
687 .c_ulonglong_type => return out_stream.writeAll("c_ulonglong"),
688 .c_longdouble_type => return out_stream.writeAll("c_longdouble"),
689 .f16_type => return out_stream.writeAll("f16"),
690 .f32_type => return out_stream.writeAll("f32"),
691 .f64_type => return out_stream.writeAll("f64"),
692 .f80_type => return out_stream.writeAll("f80"),
693 .f128_type => return out_stream.writeAll("f128"),
694 .anyopaque_type => return out_stream.writeAll("anyopaque"),
695 .bool_type => return out_stream.writeAll("bool"),
696 .void_type => return out_stream.writeAll("void"),
697 .type_type => return out_stream.writeAll("type"),
698 .anyerror_type => return out_stream.writeAll("anyerror"),
699 .comptime_int_type => return out_stream.writeAll("comptime_int"),
700 .comptime_float_type => return out_stream.writeAll("comptime_float"),
701 .noreturn_type => return out_stream.writeAll("noreturn"),
702 .null_type => return out_stream.writeAll("@Type(.Null)"),
703 .undefined_type => return out_stream.writeAll("@Type(.Undefined)"),
704 .fn_noreturn_no_args_type => return out_stream.writeAll("fn() noreturn"),
705 .fn_void_no_args_type => return out_stream.writeAll("fn() void"),
706 .fn_naked_noreturn_no_args_type => return out_stream.writeAll("fn() callconv(.Naked) noreturn"),
707 .fn_ccc_void_no_args_type => return out_stream.writeAll("fn() callconv(.C) void"),
708 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
709 .anyframe_type => return out_stream.writeAll("anyframe"),
710 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
711 .const_slice_u8_sentinel_0_type => return out_stream.writeAll("[:0]const u8"),
712 .anyerror_void_error_union_type => return out_stream.writeAll("anyerror!void"),
713 .generic_poison_type => return out_stream.writeAll("(generic poison type)"),
714 .generic_poison => return out_stream.writeAll("(generic poison)"),
715 .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
716 .manyptr_u8_type => return out_stream.writeAll("[*]u8"),
717 .manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"),
718 .manyptr_const_u8_sentinel_0_type => return out_stream.writeAll("[*:0]const u8"),
719 .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"),
720 .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"),
721 .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"),
722 .address_space_type => return out_stream.writeAll("std.builtin.AddressSpace"),
723 .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"),
724 .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"),
725 .modifier_type => return out_stream.writeAll("std.builtin.CallModifier"),
726 .prefetch_options_type => return out_stream.writeAll("std.builtin.PrefetchOptions"),
727 .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"),
728 .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"),
729 .type_info_type => return out_stream.writeAll("std.builtin.Type"),
730
731 .empty_struct_value => return out_stream.writeAll("struct {}{}"),
732250 .aggregate => {
733251 return out_stream.writeAll("(aggregate)");
734252 },
735253 .@"union" => {
736254 return out_stream.writeAll("(union value)");
737255 },
738 .null_value => return out_stream.writeAll("null"),
739 .undef => return out_stream.writeAll("undefined"),
740 .zero => return out_stream.writeAll("0"),
741 .one => return out_stream.writeAll("1"),
742 .void_value => return out_stream.writeAll("{}"),
743 .unreachable_value => return out_stream.writeAll("unreachable"),
744 .the_only_possible_value => return out_stream.writeAll("(the only possible value)"),
745 .bool_true => return out_stream.writeAll("true"),
746 .bool_false => return out_stream.writeAll("false"),
747 .ty => return val.castTag(.ty).?.data.dump("", options, out_stream),
748 .lazy_align => {
749 try out_stream.writeAll("@alignOf(");
750 try val.castTag(.lazy_align).?.data.dump("", options, out_stream);
751 return try out_stream.writeAll(")");
752 },
753 .lazy_size => {
754 try out_stream.writeAll("@sizeOf(");
755 try val.castTag(.lazy_size).?.data.dump("", options, out_stream);
756 return try out_stream.writeAll(")");
757 },
758 .int_type => {
759 const int_type = val.castTag(.int_type).?.data;
760 return out_stream.print("{s}{d}", .{
761 if (int_type.signed) "s" else "u",
762 int_type.bits,
763 });
764 },
765 .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", options, out_stream),
766 .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", options, out_stream),
767 .int_big_positive => return out_stream.print("{}", .{val.castTag(.int_big_positive).?.asBigInt()}),
768 .int_big_negative => return out_stream.print("{}", .{val.castTag(.int_big_negative).?.asBigInt()}),
769 .runtime_value => return out_stream.writeAll("[runtime value]"),
770 .function => return out_stream.print("(function decl={d})", .{val.castTag(.function).?.data.owner_decl}),
771 .extern_fn => return out_stream.writeAll("(extern function)"),
772 .variable => return out_stream.writeAll("(variable)"),
773 .decl_ref_mut => {
774 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
775 return out_stream.print("(decl_ref_mut {d})", .{decl_index});
776 },
777 .decl_ref => {
778 const decl_index = val.castTag(.decl_ref).?.data;
779 return out_stream.print("(decl_ref {d})", .{decl_index});
780 },
781 .comptime_field_ptr => {
782 return out_stream.writeAll("(comptime_field_ptr)");
783 },
784 .elem_ptr => {
785 const elem_ptr = val.castTag(.elem_ptr).?.data;
786 try out_stream.print("&[{}] ", .{elem_ptr.index});
787 val = elem_ptr.array_ptr;
788 },
789 .field_ptr => {
790 const field_ptr = val.castTag(.field_ptr).?.data;
791 try out_stream.print("fieldptr({d}) ", .{field_ptr.field_index});
792 val = field_ptr.container_ptr;
793 },
794 .empty_array => return out_stream.writeAll(".{}"),
795 .enum_literal => return out_stream.print(".{}", .{std.zig.fmtId(val.castTag(.enum_literal).?.data)}),
796 .enum_field_index => return out_stream.print("(enum field {d})", .{val.castTag(.enum_field_index).?.data}),
797256 .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}),
798 .str_lit => {
799 const str_lit = val.castTag(.str_lit).?.data;
800 return out_stream.print("(.str_lit index={d} len={d})", .{
801 str_lit.index, str_lit.len,
802 });
803 },
804257 .repeated => {
805258 try out_stream.writeAll("(repeated) ");
806259 val = val.castTag(.repeated).?.data;
807260 },
808 .empty_array_sentinel => return out_stream.writeAll("(empty array with sentinel)"),
809 .slice => return out_stream.writeAll("(slice)"),
810 .float_16 => return out_stream.print("{}", .{val.castTag(.float_16).?.data}),
811 .float_32 => return out_stream.print("{}", .{val.castTag(.float_32).?.data}),
812 .float_64 => return out_stream.print("{}", .{val.castTag(.float_64).?.data}),
813 .float_80 => return out_stream.print("{}", .{val.castTag(.float_80).?.data}),
814 .float_128 => return out_stream.print("{}", .{val.castTag(.float_128).?.data}),
815 .@"error" => return out_stream.print("error.{s}", .{val.castTag(.@"error").?.data.name}),
816261 .eu_payload => {
817262 try out_stream.writeAll("(eu_payload) ");
818 val = val.castTag(.eu_payload).?.data;
263 val = val.castTag(.repeated).?.data;
819264 },
820265 .opt_payload => {
821266 try out_stream.writeAll("(opt_payload) ");
822 val = val.castTag(.opt_payload).?.data;
823 },
824 .inferred_alloc => return out_stream.writeAll("(inferred allocation value)"),
825 .inferred_alloc_comptime => return out_stream.writeAll("(inferred comptime allocation value)"),
826 .eu_payload_ptr => {
827 try out_stream.writeAll("(eu_payload_ptr)");
828 val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
829 },
830 .opt_payload_ptr => {
831 try out_stream.writeAll("(opt_payload_ptr)");
832 val = val.castTag(.opt_payload_ptr).?.data.container_ptr;
267 val = val.castTag(.repeated).?.data;
833268 },
269 .slice => return out_stream.writeAll("(slice)"),
834270 };
835271 }
836272
......@@ -845,421 +281,404 @@ pub const Value = extern union {
845281 } };
846282 }
847283
284 /// Asserts that the value is representable as an array of bytes.
285 /// Returns the value as a null-terminated string stored in the InternPool.
286 pub fn toIpString(val: Value, ty: Type, mod: *Module) !InternPool.NullTerminatedString {
287 const ip = &mod.intern_pool;
288 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
289 .enum_literal => |enum_literal| enum_literal,
290 .ptr => |ptr| switch (ptr.len) {
291 .none => unreachable,
292 else => try arrayToIpString(val, ptr.len.toValue().toUnsignedInt(mod), mod),
293 },
294 .aggregate => |aggregate| switch (aggregate.storage) {
295 .bytes => |bytes| try ip.getOrPutString(mod.gpa, bytes),
296 .elems => try arrayToIpString(val, ty.arrayLen(mod), mod),
297 .repeated_elem => |elem| {
298 const byte = @intCast(u8, elem.toValue().toUnsignedInt(mod));
299 const len = @intCast(usize, ty.arrayLen(mod));
300 try ip.string_bytes.appendNTimes(mod.gpa, byte, len);
301 return ip.getOrPutTrailingString(mod.gpa, len);
302 },
303 },
304 else => unreachable,
305 };
306 }
307
848308 /// Asserts that the value is representable as an array of bytes.
849309 /// Copies the value into a freshly allocated slice of memory, which is owned by the caller.
850310 pub fn toAllocatedBytes(val: Value, ty: Type, allocator: Allocator, mod: *Module) ![]u8 {
851 const target = mod.getTarget();
852 switch (val.tag()) {
853 .bytes => {
854 const bytes = val.castTag(.bytes).?.data;
855 const adjusted_len = bytes.len - @boolToInt(ty.sentinel() != null);
856 const adjusted_bytes = bytes[0..adjusted_len];
857 return allocator.dupe(u8, adjusted_bytes);
858 },
859 .str_lit => {
860 const str_lit = val.castTag(.str_lit).?.data;
861 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
862 return allocator.dupe(u8, bytes);
863 },
864 .enum_literal => return allocator.dupe(u8, val.castTag(.enum_literal).?.data),
865 .repeated => {
866 const byte = @intCast(u8, val.castTag(.repeated).?.data.toUnsignedInt(target));
867 const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen()));
868 @memset(result, byte);
869 return result;
870 },
871 .decl_ref => {
872 const decl_index = val.castTag(.decl_ref).?.data;
873 const decl = mod.declPtr(decl_index);
874 const decl_val = try decl.value();
875 return decl_val.toAllocatedBytes(decl.ty, allocator, mod);
876 },
877 .the_only_possible_value => return &[_]u8{},
878 .slice => {
879 const slice = val.castTag(.slice).?.data;
880 return arrayToAllocatedBytes(slice.ptr, slice.len.toUnsignedInt(target), allocator, mod);
311 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
312 .enum_literal => |enum_literal| allocator.dupe(u8, mod.intern_pool.stringToSlice(enum_literal)),
313 .ptr => |ptr| switch (ptr.len) {
314 .none => unreachable,
315 else => try arrayToAllocatedBytes(val, ptr.len.toValue().toUnsignedInt(mod), allocator, mod),
316 },
317 .aggregate => |aggregate| switch (aggregate.storage) {
318 .bytes => |bytes| try allocator.dupe(u8, bytes),
319 .elems => try arrayToAllocatedBytes(val, ty.arrayLen(mod), allocator, mod),
320 .repeated_elem => |elem| {
321 const byte = @intCast(u8, elem.toValue().toUnsignedInt(mod));
322 const result = try allocator.alloc(u8, @intCast(usize, ty.arrayLen(mod)));
323 @memset(result, byte);
324 return result;
325 },
881326 },
882 else => return arrayToAllocatedBytes(val, ty.arrayLen(), allocator, mod),
883 }
327 else => unreachable,
328 };
884329 }
885330
886331 fn arrayToAllocatedBytes(val: Value, len: u64, allocator: Allocator, mod: *Module) ![]u8 {
887332 const result = try allocator.alloc(u8, @intCast(usize, len));
888 var elem_value_buf: ElemValueBuffer = undefined;
889333 for (result, 0..) |*elem, i| {
890 const elem_val = val.elemValueBuffer(mod, i, &elem_value_buf);
891 elem.* = @intCast(u8, elem_val.toUnsignedInt(mod.getTarget()));
334 const elem_val = try val.elemValue(mod, i);
335 elem.* = @intCast(u8, elem_val.toUnsignedInt(mod));
892336 }
893337 return result;
894338 }
895339
896 pub const ToTypeBuffer = Type.Payload.Bits;
897
898 /// Asserts that the value is representable as a type.
899 pub fn toType(self: Value, buffer: *ToTypeBuffer) Type {
900 return switch (self.tag()) {
901 .ty => self.castTag(.ty).?.data,
902 .u1_type => Type.initTag(.u1),
903 .u8_type => Type.initTag(.u8),
904 .i8_type => Type.initTag(.i8),
905 .u16_type => Type.initTag(.u16),
906 .i16_type => Type.initTag(.i16),
907 .u29_type => Type.initTag(.u29),
908 .u32_type => Type.initTag(.u32),
909 .i32_type => Type.initTag(.i32),
910 .u64_type => Type.initTag(.u64),
911 .i64_type => Type.initTag(.i64),
912 .u128_type => Type.initTag(.u128),
913 .i128_type => Type.initTag(.i128),
914 .usize_type => Type.initTag(.usize),
915 .isize_type => Type.initTag(.isize),
916 .c_char_type => Type.initTag(.c_char),
917 .c_short_type => Type.initTag(.c_short),
918 .c_ushort_type => Type.initTag(.c_ushort),
919 .c_int_type => Type.initTag(.c_int),
920 .c_uint_type => Type.initTag(.c_uint),
921 .c_long_type => Type.initTag(.c_long),
922 .c_ulong_type => Type.initTag(.c_ulong),
923 .c_longlong_type => Type.initTag(.c_longlong),
924 .c_ulonglong_type => Type.initTag(.c_ulonglong),
925 .c_longdouble_type => Type.initTag(.c_longdouble),
926 .f16_type => Type.initTag(.f16),
927 .f32_type => Type.initTag(.f32),
928 .f64_type => Type.initTag(.f64),
929 .f80_type => Type.initTag(.f80),
930 .f128_type => Type.initTag(.f128),
931 .anyopaque_type => Type.initTag(.anyopaque),
932 .bool_type => Type.initTag(.bool),
933 .void_type => Type.initTag(.void),
934 .type_type => Type.initTag(.type),
935 .anyerror_type => Type.initTag(.anyerror),
936 .comptime_int_type => Type.initTag(.comptime_int),
937 .comptime_float_type => Type.initTag(.comptime_float),
938 .noreturn_type => Type.initTag(.noreturn),
939 .null_type => Type.initTag(.null),
940 .undefined_type => Type.initTag(.undefined),
941 .fn_noreturn_no_args_type => Type.initTag(.fn_noreturn_no_args),
942 .fn_void_no_args_type => Type.initTag(.fn_void_no_args),
943 .fn_naked_noreturn_no_args_type => Type.initTag(.fn_naked_noreturn_no_args),
944 .fn_ccc_void_no_args_type => Type.initTag(.fn_ccc_void_no_args),
945 .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int),
946 .anyframe_type => Type.initTag(.@"anyframe"),
947 .const_slice_u8_type => Type.initTag(.const_slice_u8),
948 .const_slice_u8_sentinel_0_type => Type.initTag(.const_slice_u8_sentinel_0),
949 .anyerror_void_error_union_type => Type.initTag(.anyerror_void_error_union),
950 .generic_poison_type => Type.initTag(.generic_poison),
951 .enum_literal_type => Type.initTag(.enum_literal),
952 .manyptr_u8_type => Type.initTag(.manyptr_u8),
953 .manyptr_const_u8_type => Type.initTag(.manyptr_const_u8),
954 .manyptr_const_u8_sentinel_0_type => Type.initTag(.manyptr_const_u8_sentinel_0),
955 .atomic_order_type => Type.initTag(.atomic_order),
956 .atomic_rmw_op_type => Type.initTag(.atomic_rmw_op),
957 .calling_convention_type => Type.initTag(.calling_convention),
958 .address_space_type => Type.initTag(.address_space),
959 .float_mode_type => Type.initTag(.float_mode),
960 .reduce_op_type => Type.initTag(.reduce_op),
961 .modifier_type => Type.initTag(.modifier),
962 .prefetch_options_type => Type.initTag(.prefetch_options),
963 .export_options_type => Type.initTag(.export_options),
964 .extern_options_type => Type.initTag(.extern_options),
965 .type_info_type => Type.initTag(.type_info),
966
967 .int_type => {
968 const payload = self.castTag(.int_type).?.data;
969 buffer.* = .{
970 .base = .{
971 .tag = if (payload.signed) .int_signed else .int_unsigned,
972 },
973 .data = payload.bits,
974 };
975 return Type.initPayload(&buffer.base);
976 },
977
978 else => unreachable,
979 };
340 fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTerminatedString {
341 const gpa = mod.gpa;
342 const ip = &mod.intern_pool;
343 const len = @intCast(usize, len_u64);
344 try ip.string_bytes.ensureUnusedCapacity(gpa, len);
345 for (0..len) |i| {
346 // I don't think elemValue has the possibility to affect ip.string_bytes. Let's
347 // assert just to be sure.
348 const prev = ip.string_bytes.items.len;
349 const elem_val = try val.elemValue(mod, i);
350 assert(ip.string_bytes.items.len == prev);
351 const byte = @intCast(u8, elem_val.toUnsignedInt(mod));
352 ip.string_bytes.appendAssumeCapacity(byte);
353 }
354 return ip.getOrPutTrailingString(gpa, len);
980355 }
981356
982 /// Asserts the type is an enum type.
983 pub fn toEnum(val: Value, comptime E: type) E {
357 pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index {
358 if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern();
984359 switch (val.tag()) {
985 .enum_field_index => {
986 const field_index = val.castTag(.enum_field_index).?.data;
987 return @intToEnum(E, field_index);
360 .eu_payload => {
361 const pl = val.castTag(.eu_payload).?.data;
362 return mod.intern(.{ .error_union = .{
363 .ty = ty.toIntern(),
364 .val = .{ .payload = try pl.intern(ty.errorUnionPayload(mod), mod) },
365 } });
366 },
367 .opt_payload => {
368 const pl = val.castTag(.opt_payload).?.data;
369 return mod.intern(.{ .opt = .{
370 .ty = ty.toIntern(),
371 .val = try pl.intern(ty.optionalChild(mod), mod),
372 } });
988373 },
989 .the_only_possible_value => {
990 const fields = std.meta.fields(E);
991 assert(fields.len == 1);
992 return @intToEnum(E, fields[0].value);
374 .slice => {
375 const pl = val.castTag(.slice).?.data;
376 const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
377 var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;
378 assert(ptr_key.len == .none);
379 ptr_key.ty = ty.toIntern();
380 ptr_key.len = try pl.len.intern(Type.usize, mod);
381 return mod.intern(.{ .ptr = ptr_key });
382 },
383 .bytes => {
384 const pl = val.castTag(.bytes).?.data;
385 return mod.intern(.{ .aggregate = .{
386 .ty = ty.toIntern(),
387 .storage = .{ .bytes = pl },
388 } });
389 },
390 .repeated => {
391 const pl = val.castTag(.repeated).?.data;
392 return mod.intern(.{ .aggregate = .{
393 .ty = ty.toIntern(),
394 .storage = .{ .repeated_elem = try pl.intern(ty.childType(mod), mod) },
395 } });
396 },
397 .aggregate => {
398 const len = @intCast(usize, ty.arrayLen(mod));
399 const old_elems = val.castTag(.aggregate).?.data[0..len];
400 const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len);
401 defer mod.gpa.free(new_elems);
402 const ty_key = mod.intern_pool.indexToKey(ty.toIntern());
403 for (new_elems, old_elems, 0..) |*new_elem, old_elem, field_i|
404 new_elem.* = try old_elem.intern(switch (ty_key) {
405 .struct_type => ty.structFieldType(field_i, mod),
406 .anon_struct_type => |info| info.types[field_i].toType(),
407 inline .array_type, .vector_type => |info| info.child.toType(),
408 else => unreachable,
409 }, mod);
410 return mod.intern(.{ .aggregate = .{
411 .ty = ty.toIntern(),
412 .storage = .{ .elems = new_elems },
413 } });
414 },
415 .@"union" => {
416 const pl = val.castTag(.@"union").?.data;
417 return mod.intern(.{ .un = .{
418 .ty = ty.toIntern(),
419 .tag = try pl.tag.intern(ty.unionTagTypeHypothetical(mod), mod),
420 .val = try pl.val.intern(ty.unionFieldType(pl.tag, mod), mod),
421 } });
993422 },
994 else => unreachable,
995423 }
996424 }
997425
998 pub fn enumToInt(val: Value, ty: Type, buffer: *Payload.U64) Value {
999 const field_index = switch (val.tag()) {
1000 .enum_field_index => val.castTag(.enum_field_index).?.data,
1001 .the_only_possible_value => blk: {
1002 assert(ty.enumFieldCount() == 1);
1003 break :blk 0;
1004 },
1005 .enum_literal => i: {
1006 const name = val.castTag(.enum_literal).?.data;
1007 break :i ty.enumFieldIndex(name).?;
426 pub fn unintern(val: Value, arena: Allocator, mod: *Module) Allocator.Error!Value {
427 return if (val.ip_index == .none) val else switch (mod.intern_pool.indexToKey(val.toIntern())) {
428 .int_type,
429 .ptr_type,
430 .array_type,
431 .vector_type,
432 .opt_type,
433 .anyframe_type,
434 .error_union_type,
435 .simple_type,
436 .struct_type,
437 .anon_struct_type,
438 .union_type,
439 .opaque_type,
440 .enum_type,
441 .func_type,
442 .error_set_type,
443 .inferred_error_set_type,
444
445 .undef,
446 .runtime_value,
447 .simple_value,
448 .variable,
449 .extern_func,
450 .func,
451 .int,
452 .err,
453 .enum_literal,
454 .enum_tag,
455 .empty_enum_value,
456 .float,
457 => val,
458
459 .error_union => |error_union| switch (error_union.val) {
460 .err_name => val,
461 .payload => |payload| Tag.eu_payload.create(arena, payload.toValue()),
1008462 },
1009 // Assume it is already an integer and return it directly.
1010 else => return val,
1011 };
1012463
1013 switch (ty.tag()) {
1014 .enum_full, .enum_nonexhaustive => {
1015 const enum_full = ty.cast(Type.Payload.EnumFull).?.data;
1016 if (enum_full.values.count() != 0) {
1017 return enum_full.values.keys()[field_index];
1018 } else {
1019 // Field index and integer values are the same.
1020 buffer.* = .{
1021 .base = .{ .tag = .int_u64 },
1022 .data = field_index,
1023 };
1024 return Value.initPayload(&buffer.base);
1025 }
464 .ptr => |ptr| switch (ptr.len) {
465 .none => val,
466 else => |len| Tag.slice.create(arena, .{
467 .ptr = val.slicePtr(mod),
468 .len = len.toValue(),
469 }),
1026470 },
1027 .enum_numbered => {
1028 const enum_obj = ty.castTag(.enum_numbered).?.data;
1029 if (enum_obj.values.count() != 0) {
1030 return enum_obj.values.keys()[field_index];
1031 } else {
1032 // Field index and integer values are the same.
1033 buffer.* = .{
1034 .base = .{ .tag = .int_u64 },
1035 .data = field_index,
1036 };
1037 return Value.initPayload(&buffer.base);
1038 }
471
472 .opt => |opt| switch (opt.val) {
473 .none => val,
474 else => |payload| Tag.opt_payload.create(arena, payload.toValue()),
1039475 },
1040 .enum_simple => {
1041 // Field index and integer values are the same.
1042 buffer.* = .{
1043 .base = .{ .tag = .int_u64 },
1044 .data = field_index,
1045 };
1046 return Value.initPayload(&buffer.base);
476
477 .aggregate => |aggregate| switch (aggregate.storage) {
478 .bytes => |bytes| Tag.bytes.create(arena, try arena.dupe(u8, bytes)),
479 .elems => |old_elems| {
480 const new_elems = try arena.alloc(Value, old_elems.len);
481 for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = old_elem.toValue();
482 return Tag.aggregate.create(arena, new_elems);
483 },
484 .repeated_elem => |elem| Tag.repeated.create(arena, elem.toValue()),
1047485 },
1048 else => unreachable,
1049 }
486
487 .un => |un| Tag.@"union".create(arena, .{
488 .tag = un.tag.toValue(),
489 .val = un.val.toValue(),
490 }),
491
492 .memoized_call => unreachable,
493 };
1050494 }
1051495
1052 pub fn tagName(val: Value, ty: Type, mod: *Module) []const u8 {
1053 if (ty.zigTypeTag() == .Union) return val.unionTag().tagName(ty.unionTagTypeHypothetical(), mod);
496 pub fn toIntern(val: Value) InternPool.Index {
497 assert(val.ip_index != .none);
498 return val.ip_index;
499 }
1054500
1055 const field_index = switch (val.tag()) {
1056 .enum_field_index => val.castTag(.enum_field_index).?.data,
1057 .the_only_possible_value => blk: {
1058 assert(ty.enumFieldCount() == 1);
1059 break :blk 0;
1060 },
1061 .enum_literal => return val.castTag(.enum_literal).?.data,
1062 else => field_index: {
1063 const values = switch (ty.tag()) {
1064 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values,
1065 .enum_numbered => ty.castTag(.enum_numbered).?.data.values,
1066 .enum_simple => Module.EnumFull.ValueMap{},
501 /// Asserts that the value is representable as a type.
502 pub fn toType(self: Value) Type {
503 return self.toIntern().toType();
504 }
505
506 pub fn enumToInt(val: Value, ty: Type, mod: *Module) Allocator.Error!Value {
507 const ip = &mod.intern_pool;
508 return switch (ip.indexToKey(ip.typeOf(val.toIntern()))) {
509 // Assume it is already an integer and return it directly.
510 .simple_type, .int_type => val,
511 .enum_literal => |enum_literal| {
512 const field_index = ty.enumFieldIndex(enum_literal, mod).?;
513 return switch (ip.indexToKey(ty.toIntern())) {
514 // Assume it is already an integer and return it directly.
515 .simple_type, .int_type => val,
516 .enum_type => |enum_type| if (enum_type.values.len != 0)
517 enum_type.values[field_index].toValue()
518 else // Field index and integer values are the same.
519 mod.intValue(enum_type.tag_ty.toType(), field_index),
1067520 else => unreachable,
1068521 };
1069 if (values.entries.len == 0) {
1070 // auto-numbered enum
1071 break :field_index @intCast(u32, val.toUnsignedInt(mod.getTarget()));
1072 }
1073 var buffer: Type.Payload.Bits = undefined;
1074 const int_tag_ty = ty.intTagType(&buffer);
1075 break :field_index @intCast(u32, values.getIndexContext(val, .{ .ty = int_tag_ty, .mod = mod }).?);
1076522 },
1077 };
1078
1079 const fields = switch (ty.tag()) {
1080 .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.fields,
1081 .enum_numbered => ty.castTag(.enum_numbered).?.data.fields,
1082 .enum_simple => ty.castTag(.enum_simple).?.data.fields,
523 .enum_type => |enum_type| try mod.getCoerced(val, enum_type.tag_ty.toType()),
1083524 else => unreachable,
1084525 };
1085 return fields.keys()[field_index];
1086526 }
1087527
1088528 /// Asserts the value is an integer.
1089 pub fn toBigInt(val: Value, space: *BigIntSpace, target: Target) BigIntConst {
1090 return val.toBigIntAdvanced(space, target, null) catch unreachable;
529 pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *Module) BigIntConst {
530 return val.toBigIntAdvanced(space, mod, null) catch unreachable;
1091531 }
1092532
1093533 /// Asserts the value is an integer.
1094534 pub fn toBigIntAdvanced(
1095535 val: Value,
1096536 space: *BigIntSpace,
1097 target: Target,
537 mod: *Module,
1098538 opt_sema: ?*Sema,
1099539 ) Module.CompileError!BigIntConst {
1100 switch (val.tag()) {
1101 .null_value,
1102 .zero,
1103 .bool_false,
1104 .the_only_possible_value, // i0, u0
1105 => return BigIntMutable.init(&space.limbs, 0).toConst(),
1106
1107 .one,
1108 .bool_true,
1109 => return BigIntMutable.init(&space.limbs, 1).toConst(),
1110
1111 .enum_field_index => {
1112 const index = val.castTag(.enum_field_index).?.data;
1113 return BigIntMutable.init(&space.limbs, index).toConst();
1114 },
1115 .runtime_value => {
1116 const sub_val = val.castTag(.runtime_value).?.data;
1117 return sub_val.toBigIntAdvanced(space, target, opt_sema);
540 return switch (val.toIntern()) {
541 .bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
542 .bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
543 .null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
544 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
545 .runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
546 .int => |int| switch (int.storage) {
547 .u64, .i64, .big_int => int.storage.toBigInt(space),
548 .lazy_align, .lazy_size => |ty| {
549 if (opt_sema) |sema| try sema.resolveTypeLayout(ty.toType());
550 const x = switch (int.storage) {
551 else => unreachable,
552 .lazy_align => ty.toType().abiAlignment(mod),
553 .lazy_size => ty.toType().abiSize(mod),
554 };
555 return BigIntMutable.init(&space.limbs, x).toConst();
556 },
557 },
558 .enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),
559 .opt, .ptr => BigIntMutable.init(
560 &space.limbs,
561 (try val.getUnsignedIntAdvanced(mod, opt_sema)).?,
562 ).toConst(),
563 else => unreachable,
1118564 },
1119 .int_u64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_u64).?.data).toConst(),
1120 .int_i64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_i64).?.data).toConst(),
1121 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(),
1122 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(),
565 };
566 }
1123567
1124 .undef => unreachable,
568 pub fn getFunction(val: Value, mod: *Module) ?*Module.Fn {
569 return mod.funcPtrUnwrap(val.getFunctionIndex(mod));
570 }
1125571
1126 .lazy_align => {
1127 const ty = val.castTag(.lazy_align).?.data;
1128 if (opt_sema) |sema| {
1129 try sema.resolveTypeLayout(ty);
1130 }
1131 const x = ty.abiAlignment(target);
1132 return BigIntMutable.init(&space.limbs, x).toConst();
1133 },
1134 .lazy_size => {
1135 const ty = val.castTag(.lazy_size).?.data;
1136 if (opt_sema) |sema| {
1137 try sema.resolveTypeLayout(ty);
1138 }
1139 const x = ty.abiSize(target);
1140 return BigIntMutable.init(&space.limbs, x).toConst();
1141 },
572 pub fn getFunctionIndex(val: Value, mod: *Module) Module.Fn.OptionalIndex {
573 return if (val.ip_index != .none) mod.intern_pool.indexToFunc(val.toIntern()) else .none;
574 }
1142575
1143 .elem_ptr => {
1144 const elem_ptr = val.castTag(.elem_ptr).?.data;
1145 const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(target, opt_sema)).?;
1146 const elem_size = elem_ptr.elem_ty.abiSize(target);
1147 const new_addr = array_addr + elem_size * elem_ptr.index;
1148 return BigIntMutable.init(&space.limbs, new_addr).toConst();
1149 },
576 pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc {
577 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {
578 .extern_func => |extern_func| extern_func,
579 else => null,
580 } else null;
581 }
1150582
1151 else => unreachable,
1152 }
583 pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable {
584 return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) {
585 .variable => |variable| variable,
586 else => null,
587 } else null;
1153588 }
1154589
1155590 /// If the value fits in a u64, return it, otherwise null.
1156591 /// Asserts not undefined.
1157 pub fn getUnsignedInt(val: Value, target: Target) ?u64 {
1158 return getUnsignedIntAdvanced(val, target, null) catch unreachable;
592 pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 {
593 return getUnsignedIntAdvanced(val, mod, null) catch unreachable;
1159594 }
1160595
1161596 /// If the value fits in a u64, return it, otherwise null.
1162597 /// Asserts not undefined.
1163 pub fn getUnsignedIntAdvanced(val: Value, target: Target, opt_sema: ?*Sema) !?u64 {
1164 switch (val.tag()) {
1165 .zero,
1166 .bool_false,
1167 .the_only_possible_value, // i0, u0
1168 => return 0,
1169
1170 .one,
1171 .bool_true,
1172 => return 1,
1173
1174 .int_u64 => return val.castTag(.int_u64).?.data,
1175 .int_i64 => return @intCast(u64, val.castTag(.int_i64).?.data),
1176 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null,
1177 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null,
1178
598 pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
599 return switch (val.toIntern()) {
1179600 .undef => unreachable,
1180
1181 .lazy_align => {
1182 const ty = val.castTag(.lazy_align).?.data;
1183 if (opt_sema) |sema| {
1184 return (try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar;
1185 } else {
1186 return ty.abiAlignment(target);
1187 }
1188 },
1189 .lazy_size => {
1190 const ty = val.castTag(.lazy_size).?.data;
1191 if (opt_sema) |sema| {
1192 return (try ty.abiSizeAdvanced(target, .{ .sema = sema })).scalar;
1193 } else {
1194 return ty.abiSize(target);
1195 }
601 .bool_false => 0,
602 .bool_true => 1,
603 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
604 .undef => unreachable,
605 .int => |int| switch (int.storage) {
606 .big_int => |big_int| big_int.to(u64) catch null,
607 .u64 => |x| x,
608 .i64 => |x| std.math.cast(u64, x),
609 .lazy_align => |ty| if (opt_sema) |sema|
610 (try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar
611 else
612 ty.toType().abiAlignment(mod),
613 .lazy_size => |ty| if (opt_sema) |sema|
614 (try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar
615 else
616 ty.toType().abiSize(mod),
617 },
618 .ptr => |ptr| switch (ptr.addr) {
619 .int => |int| int.toValue().getUnsignedIntAdvanced(mod, opt_sema),
620 .elem => |elem| {
621 const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
622 const elem_ty = mod.intern_pool.typeOf(elem.base).toType().elemType2(mod);
623 return base_addr + elem.index * elem_ty.abiSize(mod);
624 },
625 .field => |field| {
626 const base_addr = (try field.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
627 const struct_ty = mod.intern_pool.typeOf(field.base).toType().childType(mod);
628 if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty);
629 return base_addr + struct_ty.structFieldOffset(@intCast(usize, field.index), mod);
630 },
631 else => null,
632 },
633 .opt => |opt| switch (opt.val) {
634 .none => 0,
635 else => |payload| payload.toValue().getUnsignedIntAdvanced(mod, opt_sema),
636 },
637 else => null,
1196638 },
1197
1198 else => return null,
1199 }
639 };
1200640 }
1201641
1202642 /// Asserts the value is an integer and it fits in a u64
1203 pub fn toUnsignedInt(val: Value, target: Target) u64 {
1204 return getUnsignedInt(val, target).?;
643 pub fn toUnsignedInt(val: Value, mod: *Module) u64 {
644 return getUnsignedInt(val, mod).?;
1205645 }
1206646
1207647 /// Asserts the value is an integer and it fits in a i64
1208 pub fn toSignedInt(val: Value, target: Target) i64 {
1209 switch (val.tag()) {
1210 .zero,
1211 .bool_false,
1212 .the_only_possible_value, // i0, u0
1213 => return 0,
1214
1215 .one,
1216 .bool_true,
1217 => return 1,
1218
1219 .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data),
1220 .int_i64 => return val.castTag(.int_i64).?.data,
1221 .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable,
1222 .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable,
1223
1224 .lazy_align => {
1225 const ty = val.castTag(.lazy_align).?.data;
1226 return @intCast(i64, ty.abiAlignment(target));
1227 },
1228 .lazy_size => {
1229 const ty = val.castTag(.lazy_size).?.data;
1230 return @intCast(i64, ty.abiSize(target));
648 pub fn toSignedInt(val: Value, mod: *Module) i64 {
649 return switch (val.toIntern()) {
650 .bool_false => 0,
651 .bool_true => 1,
652 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
653 .int => |int| switch (int.storage) {
654 .big_int => |big_int| big_int.to(i64) catch unreachable,
655 .i64 => |x| x,
656 .u64 => |x| @intCast(i64, x),
657 .lazy_align => |ty| @intCast(i64, ty.toType().abiAlignment(mod)),
658 .lazy_size => |ty| @intCast(i64, ty.toType().abiSize(mod)),
659 },
660 else => unreachable,
1231661 },
1232
1233 .undef => unreachable,
1234 else => unreachable,
1235 }
662 };
1236663 }
1237664
1238 pub fn toBool(self: Value) bool {
1239 return switch (self.tag()) {
1240 .bool_true, .one => true,
1241 .bool_false, .zero => false,
1242 .int_u64 => switch (self.castTag(.int_u64).?.data) {
1243 0 => false,
1244 1 => true,
1245 else => unreachable,
1246 },
1247 .int_i64 => switch (self.castTag(.int_i64).?.data) {
1248 0 => false,
1249 1 => true,
1250 else => unreachable,
1251 },
665 pub fn toBool(val: Value) bool {
666 return switch (val.toIntern()) {
667 .bool_true => true,
668 .bool_false => false,
1252669 else => unreachable,
1253670 };
1254671 }
1255672
1256 fn isDeclRef(val: Value) bool {
673 fn isDeclRef(val: Value, mod: *Module) bool {
1257674 var check = val;
1258 while (true) switch (check.tag()) {
1259 .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return true,
1260 .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr,
1261 .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr,
1262 .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr,
675 while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) {
676 .ptr => |ptr| switch (ptr.addr) {
677 .decl, .mut_decl, .comptime_field => return true,
678 .eu_payload, .opt_payload => |base| check = base.toValue(),
679 .elem, .field => |base_index| check = base_index.base.toValue(),
680 else => return false,
681 },
1263682 else => return false,
1264683 };
1265684 }
......@@ -1272,62 +691,45 @@ pub const Value = extern union {
1272691 ReinterpretDeclRef,
1273692 IllDefinedMemoryLayout,
1274693 Unimplemented,
694 OutOfMemory,
1275695 }!void {
1276696 const target = mod.getTarget();
1277697 const endian = target.cpu.arch.endian();
1278 if (val.isUndef()) {
1279 const size = @intCast(usize, ty.abiSize(target));
698 if (val.isUndef(mod)) {
699 const size = @intCast(usize, ty.abiSize(mod));
1280700 @memset(buffer[0..size], 0xaa);
1281701 return;
1282702 }
1283 switch (ty.zigTypeTag()) {
703 switch (ty.zigTypeTag(mod)) {
1284704 .Void => {},
1285705 .Bool => {
1286706 buffer[0] = @boolToInt(val.toBool());
1287707 },
1288708 .Int, .Enum => {
1289 const int_info = ty.intInfo(target);
709 const int_info = ty.intInfo(mod);
1290710 const bits = int_info.bits;
1291711 const byte_count = (bits + 7) / 8;
1292712
1293 var enum_buffer: Payload.U64 = undefined;
1294 const int_val = val.enumToInt(ty, &enum_buffer);
1295
1296 if (byte_count <= @sizeOf(u64)) {
1297 const int: u64 = switch (int_val.tag()) {
1298 .zero => 0,
1299 .one => 1,
1300 .int_u64 => int_val.castTag(.int_u64).?.data,
1301 .int_i64 => @bitCast(u64, int_val.castTag(.int_i64).?.data),
1302 else => unreachable,
1303 };
1304 for (buffer[0..byte_count], 0..) |_, i| switch (endian) {
1305 .Little => buffer[i] = @truncate(u8, (int >> @intCast(u6, (8 * i)))),
1306 .Big => buffer[byte_count - i - 1] = @truncate(u8, (int >> @intCast(u6, (8 * i)))),
1307 };
1308 } else {
1309 var bigint_buffer: BigIntSpace = undefined;
1310 const bigint = int_val.toBigInt(&bigint_buffer, target);
1311 bigint.writeTwosComplement(buffer[0..byte_count], endian);
1312 }
713 var bigint_buffer: BigIntSpace = undefined;
714 const bigint = val.toBigInt(&bigint_buffer, mod);
715 bigint.writeTwosComplement(buffer[0..byte_count], endian);
1313716 },
1314717 .Float => switch (ty.floatBits(target)) {
1315 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16)), endian),
1316 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(u32, val.toFloat(f32)), endian),
1317 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(u64, val.toFloat(f64)), endian),
1318 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(u80, val.toFloat(f80)), endian),
1319 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(u128, val.toFloat(f128)), endian),
718 16 => std.mem.writeInt(u16, buffer[0..2], @bitCast(u16, val.toFloat(f16, mod)), endian),
719 32 => std.mem.writeInt(u32, buffer[0..4], @bitCast(u32, val.toFloat(f32, mod)), endian),
720 64 => std.mem.writeInt(u64, buffer[0..8], @bitCast(u64, val.toFloat(f64, mod)), endian),
721 80 => std.mem.writeInt(u80, buffer[0..10], @bitCast(u80, val.toFloat(f80, mod)), endian),
722 128 => std.mem.writeInt(u128, buffer[0..16], @bitCast(u128, val.toFloat(f128, mod)), endian),
1320723 else => unreachable,
1321724 },
1322725 .Array => {
1323 const len = ty.arrayLen();
1324 const elem_ty = ty.childType();
1325 const elem_size = @intCast(usize, elem_ty.abiSize(target));
726 const len = ty.arrayLen(mod);
727 const elem_ty = ty.childType(mod);
728 const elem_size = @intCast(usize, elem_ty.abiSize(mod));
1326729 var elem_i: usize = 0;
1327 var elem_value_buf: ElemValueBuffer = undefined;
1328730 var buf_off: usize = 0;
1329731 while (elem_i < len) : (elem_i += 1) {
1330 const elem_val = val.elemValueBuffer(mod, elem_i, &elem_value_buf);
732 const elem_val = try val.elemValue(mod, elem_i);
1331733 try elem_val.writeToMemory(elem_ty, mod, buffer[buf_off..]);
1332734 buf_off += elem_size;
1333735 }
......@@ -1335,52 +737,63 @@ pub const Value = extern union {
1335737 .Vector => {
1336738 // We use byte_count instead of abi_size here, so that any padding bytes
1337739 // follow the data bytes, on both big- and little-endian systems.
1338 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
740 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1339741 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1340742 },
1341 .Struct => switch (ty.containerLayout()) {
743 .Struct => switch (ty.containerLayout(mod)) {
1342744 .Auto => return error.IllDefinedMemoryLayout,
1343 .Extern => {
1344 const fields = ty.structFields().values();
1345 const field_vals = val.castTag(.aggregate).?.data;
1346 for (fields, 0..) |field, i| {
1347 const off = @intCast(usize, ty.structFieldOffset(i, target));
1348 try writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);
1349 }
745 .Extern => for (ty.structFields(mod).values(), 0..) |field, i| {
746 const off = @intCast(usize, ty.structFieldOffset(i, mod));
747 const field_val = switch (val.ip_index) {
748 .none => val.castTag(.aggregate).?.data[i],
749 else => switch (mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage) {
750 .bytes => |bytes| {
751 buffer[off] = bytes[i];
752 continue;
753 },
754 .elems => |elems| elems[i],
755 .repeated_elem => |elem| elem,
756 }.toValue(),
757 };
758 try writeToMemory(field_val, field.ty, mod, buffer[off..]);
1350759 },
1351760 .Packed => {
1352 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
761 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1353762 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1354763 },
1355764 },
1356765 .ErrorSet => {
1357766 // TODO revisit this when we have the concept of the error tag type
1358767 const Int = u16;
1359 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
768 const name = switch (mod.intern_pool.indexToKey(val.toIntern())) {
769 .err => |err| err.name,
770 .error_union => |error_union| error_union.val.err_name,
771 else => unreachable,
772 };
773 const int = @intCast(Module.ErrorInt, mod.global_error_set.getIndex(name).?);
1360774 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), endian);
1361775 },
1362 .Union => switch (ty.containerLayout()) {
776 .Union => switch (ty.containerLayout(mod)) {
1363777 .Auto => return error.IllDefinedMemoryLayout,
1364778 .Extern => return error.Unimplemented,
1365779 .Packed => {
1366 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
780 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1367781 return writeToPackedMemory(val, ty, mod, buffer[0..byte_count], 0);
1368782 },
1369783 },
1370784 .Pointer => {
1371 if (ty.isSlice()) return error.IllDefinedMemoryLayout;
1372 if (val.isDeclRef()) return error.ReinterpretDeclRef;
785 if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout;
786 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1373787 return val.writeToMemory(Type.usize, mod, buffer);
1374788 },
1375789 .Optional => {
1376 if (!ty.isPtrLikeOptional()) return error.IllDefinedMemoryLayout;
1377 var buf: Type.Payload.ElemType = undefined;
1378 const child = ty.optionalChild(&buf);
1379 const opt_val = val.optionalValue();
790 if (!ty.isPtrLikeOptional(mod)) return error.IllDefinedMemoryLayout;
791 const child = ty.optionalChild(mod);
792 const opt_val = val.optionalValue(mod);
1380793 if (opt_val) |some| {
1381794 return some.writeToMemory(child, mod, buffer);
1382795 } else {
1383 return writeToMemory(Value.zero, Type.usize, mod, buffer);
796 return writeToMemory(try mod.intValue(Type.usize, 0), Type.usize, mod, buffer);
1384797 }
1385798 },
1386799 else => return error.Unimplemented,
......@@ -1391,15 +804,21 @@ pub const Value = extern union {
1391804 ///
1392805 /// Both the start and the end of the provided buffer must be tight, since
1393806 /// big-endian packed memory layouts start at the end of the buffer.
1394 pub fn writeToPackedMemory(val: Value, ty: Type, mod: *Module, buffer: []u8, bit_offset: usize) error{ReinterpretDeclRef}!void {
807 pub fn writeToPackedMemory(
808 val: Value,
809 ty: Type,
810 mod: *Module,
811 buffer: []u8,
812 bit_offset: usize,
813 ) error{ ReinterpretDeclRef, OutOfMemory }!void {
1395814 const target = mod.getTarget();
1396815 const endian = target.cpu.arch.endian();
1397 if (val.isUndef()) {
1398 const bit_size = @intCast(usize, ty.bitSize(target));
816 if (val.isUndef(mod)) {
817 const bit_size = @intCast(usize, ty.bitSize(mod));
1399818 std.mem.writeVarPackedInt(buffer, bit_offset, bit_size, @as(u1, 0), endian);
1400819 return;
1401820 }
1402 switch (ty.zigTypeTag()) {
821 switch (ty.zigTypeTag(mod)) {
1403822 .Void => {},
1404823 .Bool => {
1405824 const byte_index = switch (endian) {
......@@ -1413,91 +832,82 @@ pub const Value = extern union {
1413832 }
1414833 },
1415834 .Int, .Enum => {
1416 const bits = ty.intInfo(target).bits;
1417 const abi_size = @intCast(usize, ty.abiSize(target));
1418
1419 var enum_buffer: Payload.U64 = undefined;
1420 const int_val = val.enumToInt(ty, &enum_buffer);
1421
1422 if (abi_size == 0) return;
1423 if (abi_size <= @sizeOf(u64)) {
1424 const int: u64 = switch (int_val.tag()) {
1425 .zero => 0,
1426 .one => 1,
1427 .int_u64 => int_val.castTag(.int_u64).?.data,
1428 .int_i64 => @bitCast(u64, int_val.castTag(.int_i64).?.data),
1429 else => unreachable,
1430 };
1431 std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian);
1432 } else {
1433 var bigint_buffer: BigIntSpace = undefined;
1434 const bigint = int_val.toBigInt(&bigint_buffer, target);
1435 bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian);
835 if (buffer.len == 0) return;
836 const bits = ty.intInfo(mod).bits;
837 if (bits == 0) return;
838
839 switch (mod.intern_pool.indexToKey((try val.enumToInt(ty, mod)).toIntern()).int.storage) {
840 inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
841 .big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
842 else => unreachable,
1436843 }
1437844 },
1438845 .Float => switch (ty.floatBits(target)) {
1439 16 => std.mem.writePackedInt(u16, buffer, bit_offset, @bitCast(u16, val.toFloat(f16)), endian),
1440 32 => std.mem.writePackedInt(u32, buffer, bit_offset, @bitCast(u32, val.toFloat(f32)), endian),
1441 64 => std.mem.writePackedInt(u64, buffer, bit_offset, @bitCast(u64, val.toFloat(f64)), endian),
1442 80 => std.mem.writePackedInt(u80, buffer, bit_offset, @bitCast(u80, val.toFloat(f80)), endian),
1443 128 => std.mem.writePackedInt(u128, buffer, bit_offset, @bitCast(u128, val.toFloat(f128)), endian),
846 16 => std.mem.writePackedInt(u16, buffer, bit_offset, @bitCast(u16, val.toFloat(f16, mod)), endian),
847 32 => std.mem.writePackedInt(u32, buffer, bit_offset, @bitCast(u32, val.toFloat(f32, mod)), endian),
848 64 => std.mem.writePackedInt(u64, buffer, bit_offset, @bitCast(u64, val.toFloat(f64, mod)), endian),
849 80 => std.mem.writePackedInt(u80, buffer, bit_offset, @bitCast(u80, val.toFloat(f80, mod)), endian),
850 128 => std.mem.writePackedInt(u128, buffer, bit_offset, @bitCast(u128, val.toFloat(f128, mod)), endian),
1444851 else => unreachable,
1445852 },
1446853 .Vector => {
1447 const elem_ty = ty.childType();
1448 const elem_bit_size = @intCast(u16, elem_ty.bitSize(target));
1449 const len = @intCast(usize, ty.arrayLen());
854 const elem_ty = ty.childType(mod);
855 const elem_bit_size = @intCast(u16, elem_ty.bitSize(mod));
856 const len = @intCast(usize, ty.arrayLen(mod));
1450857
1451858 var bits: u16 = 0;
1452859 var elem_i: usize = 0;
1453 var elem_value_buf: ElemValueBuffer = undefined;
1454860 while (elem_i < len) : (elem_i += 1) {
1455861 // On big-endian systems, LLVM reverses the element order of vectors by default
1456862 const tgt_elem_i = if (endian == .Big) len - elem_i - 1 else elem_i;
1457 const elem_val = val.elemValueBuffer(mod, tgt_elem_i, &elem_value_buf);
863 const elem_val = try val.elemValue(mod, tgt_elem_i);
1458864 try elem_val.writeToPackedMemory(elem_ty, mod, buffer, bit_offset + bits);
1459865 bits += elem_bit_size;
1460866 }
1461867 },
1462 .Struct => switch (ty.containerLayout()) {
868 .Struct => switch (ty.containerLayout(mod)) {
1463869 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1464870 .Extern => unreachable, // Handled in non-packed writeToMemory
1465871 .Packed => {
1466872 var bits: u16 = 0;
1467 const fields = ty.structFields().values();
1468 const field_vals = val.castTag(.aggregate).?.data;
873 const fields = ty.structFields(mod).values();
874 const storage = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage;
1469875 for (fields, 0..) |field, i| {
1470 const field_bits = @intCast(u16, field.ty.bitSize(target));
1471 try field_vals[i].writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits);
876 const field_bits = @intCast(u16, field.ty.bitSize(mod));
877 const field_val = switch (storage) {
878 .bytes => unreachable,
879 .elems => |elems| elems[i],
880 .repeated_elem => |elem| elem,
881 };
882 try field_val.toValue().writeToPackedMemory(field.ty, mod, buffer, bit_offset + bits);
1472883 bits += field_bits;
1473884 }
1474885 },
1475886 },
1476 .Union => switch (ty.containerLayout()) {
887 .Union => switch (ty.containerLayout(mod)) {
1477888 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
1478889 .Extern => unreachable, // Handled in non-packed writeToMemory
1479890 .Packed => {
1480 const field_index = ty.unionTagFieldIndex(val.unionTag(), mod);
1481 const field_type = ty.unionFields().values()[field_index.?].ty;
1482 const field_val = val.fieldValue(field_type, field_index.?);
891 const field_index = ty.unionTagFieldIndex(val.unionTag(mod), mod);
892 const field_type = ty.unionFields(mod).values()[field_index.?].ty;
893 const field_val = try val.fieldValue(mod, field_index.?);
1483894
1484895 return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
1485896 },
1486897 },
1487898 .Pointer => {
1488 assert(!ty.isSlice()); // No well defined layout.
1489 if (val.isDeclRef()) return error.ReinterpretDeclRef;
899 assert(!ty.isSlice(mod)); // No well defined layout.
900 if (val.isDeclRef(mod)) return error.ReinterpretDeclRef;
1490901 return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset);
1491902 },
1492903 .Optional => {
1493 assert(ty.isPtrLikeOptional());
1494 var buf: Type.Payload.ElemType = undefined;
1495 const child = ty.optionalChild(&buf);
1496 const opt_val = val.optionalValue();
904 assert(ty.isPtrLikeOptional(mod));
905 const child = ty.optionalChild(mod);
906 const opt_val = val.optionalValue(mod);
1497907 if (opt_val) |some| {
1498908 return some.writeToPackedMemory(child, mod, buffer, bit_offset);
1499909 } else {
1500 return writeToPackedMemory(Value.zero, Type.usize, mod, buffer, bit_offset);
910 return writeToPackedMemory(try mod.intValue(Type.usize, 0), Type.usize, mod, buffer, bit_offset);
1501911 }
1502912 },
1503913 else => @panic("TODO implement writeToPackedMemory for more types"),
......@@ -1516,7 +926,7 @@ pub const Value = extern union {
1516926 ) Allocator.Error!Value {
1517927 const target = mod.getTarget();
1518928 const endian = target.cpu.arch.endian();
1519 switch (ty.zigTypeTag()) {
929 switch (ty.zigTypeTag(mod)) {
1520930 .Void => return Value.void,
1521931 .Bool => {
1522932 if (buffer[0] == 0) {
......@@ -1525,20 +935,27 @@ pub const Value = extern union {
1525935 return Value.true;
1526936 }
1527937 },
1528 .Int, .Enum => {
1529 const int_info = ty.intInfo(target);
938 .Int, .Enum => |ty_tag| {
939 const int_ty = switch (ty_tag) {
940 .Int => ty,
941 .Enum => ty.intTagType(mod),
942 else => unreachable,
943 };
944 const int_info = int_ty.intInfo(mod);
1530945 const bits = int_info.bits;
1531946 const byte_count = (bits + 7) / 8;
1532 if (bits == 0 or buffer.len == 0) return Value.zero;
947 if (bits == 0 or buffer.len == 0) return mod.getCoerced(try mod.intValue(int_ty, 0), ty);
1533948
1534949 if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
1535950 .signed => {
1536951 const val = std.mem.readVarInt(i64, buffer[0..byte_count], endian);
1537 return Value.Tag.int_i64.create(arena, (val << @intCast(u6, 64 - bits)) >> @intCast(u6, 64 - bits));
952 const result = (val << @intCast(u6, 64 - bits)) >> @intCast(u6, 64 - bits);
953 return mod.getCoerced(try mod.intValue(int_ty, result), ty);
1538954 },
1539955 .unsigned => {
1540956 const val = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
1541 return Value.Tag.int_u64.create(arena, (val << @intCast(u6, 64 - bits)) >> @intCast(u6, 64 - bits));
957 const result = (val << @intCast(u6, 64 - bits)) >> @intCast(u6, 64 - bits);
958 return mod.getCoerced(try mod.intValue(int_ty, result), ty);
1542959 },
1543960 } else { // Slow path, we have to construct a big-int
1544961 const Limb = std.math.big.Limb;
......@@ -1547,48 +964,57 @@ pub const Value = extern union {
1547964
1548965 var bigint = BigIntMutable.init(limbs_buffer, 0);
1549966 bigint.readTwosComplement(buffer[0..byte_count], bits, endian, int_info.signedness);
1550 return fromBigInt(arena, bigint.toConst());
967 return mod.getCoerced(try mod.intValue_big(int_ty, bigint.toConst()), ty);
1551968 }
1552969 },
1553 .Float => switch (ty.floatBits(target)) {
1554 16 => return Value.Tag.float_16.create(arena, @bitCast(f16, std.mem.readInt(u16, buffer[0..2], endian))),
1555 32 => return Value.Tag.float_32.create(arena, @bitCast(f32, std.mem.readInt(u32, buffer[0..4], endian))),
1556 64 => return Value.Tag.float_64.create(arena, @bitCast(f64, std.mem.readInt(u64, buffer[0..8], endian))),
1557 80 => return Value.Tag.float_80.create(arena, @bitCast(f80, std.mem.readInt(u80, buffer[0..10], endian))),
1558 128 => return Value.Tag.float_128.create(arena, @bitCast(f128, std.mem.readInt(u128, buffer[0..16], endian))),
1559 else => unreachable,
1560 },
970 .Float => return (try mod.intern(.{ .float = .{
971 .ty = ty.toIntern(),
972 .storage = switch (ty.floatBits(target)) {
973 16 => .{ .f16 = @bitCast(f16, std.mem.readInt(u16, buffer[0..2], endian)) },
974 32 => .{ .f32 = @bitCast(f32, std.mem.readInt(u32, buffer[0..4], endian)) },
975 64 => .{ .f64 = @bitCast(f64, std.mem.readInt(u64, buffer[0..8], endian)) },
976 80 => .{ .f80 = @bitCast(f80, std.mem.readInt(u80, buffer[0..10], endian)) },
977 128 => .{ .f128 = @bitCast(f128, std.mem.readInt(u128, buffer[0..16], endian)) },
978 else => unreachable,
979 },
980 } })).toValue(),
1561981 .Array => {
1562 const elem_ty = ty.childType();
1563 const elem_size = elem_ty.abiSize(target);
1564 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));
982 const elem_ty = ty.childType(mod);
983 const elem_size = elem_ty.abiSize(mod);
984 const elems = try arena.alloc(InternPool.Index, @intCast(usize, ty.arrayLen(mod)));
1565985 var offset: usize = 0;
1566986 for (elems) |*elem| {
1567 elem.* = try readFromMemory(elem_ty, mod, buffer[offset..], arena);
987 elem.* = try (try readFromMemory(elem_ty, mod, buffer[offset..], arena)).intern(elem_ty, mod);
1568988 offset += @intCast(usize, elem_size);
1569989 }
1570 return Tag.aggregate.create(arena, elems);
990 return (try mod.intern(.{ .aggregate = .{
991 .ty = ty.toIntern(),
992 .storage = .{ .elems = elems },
993 } })).toValue();
1571994 },
1572995 .Vector => {
1573996 // We use byte_count instead of abi_size here, so that any padding bytes
1574997 // follow the data bytes, on both big- and little-endian systems.
1575 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
998 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
1576999 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);
15771000 },
1578 .Struct => switch (ty.containerLayout()) {
1001 .Struct => switch (ty.containerLayout(mod)) {
15791002 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
15801003 .Extern => {
1581 const fields = ty.structFields().values();
1582 const field_vals = try arena.alloc(Value, fields.len);
1583 for (fields, 0..) |field, i| {
1584 const off = @intCast(usize, ty.structFieldOffset(i, target));
1585 const sz = @intCast(usize, ty.structFieldType(i).abiSize(target));
1586 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena);
1004 const fields = ty.structFields(mod).values();
1005 const field_vals = try arena.alloc(InternPool.Index, fields.len);
1006 for (field_vals, fields, 0..) |*field_val, field, i| {
1007 const off = @intCast(usize, ty.structFieldOffset(i, mod));
1008 const sz = @intCast(usize, field.ty.abiSize(mod));
1009 field_val.* = try (try readFromMemory(field.ty, mod, buffer[off..(off + sz)], arena)).intern(field.ty, mod);
15871010 }
1588 return Tag.aggregate.create(arena, field_vals);
1011 return (try mod.intern(.{ .aggregate = .{
1012 .ty = ty.toIntern(),
1013 .storage = .{ .elems = field_vals },
1014 } })).toValue();
15891015 },
15901016 .Packed => {
1591 const byte_count = (@intCast(usize, ty.bitSize(target)) + 7) / 8;
1017 const byte_count = (@intCast(usize, ty.bitSize(mod)) + 7) / 8;
15921018 return readFromPackedMemory(ty, mod, buffer[0..byte_count], 0, arena);
15931019 },
15941020 },
......@@ -1596,22 +1022,19 @@ pub const Value = extern union {
15961022 // TODO revisit this when we have the concept of the error tag type
15971023 const Int = u16;
15981024 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], endian);
1599
1600 const payload = try arena.create(Value.Payload.Error);
1601 payload.* = .{
1602 .base = .{ .tag = .@"error" },
1603 .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },
1604 };
1605 return Value.initPayload(&payload.base);
1025 const name = mod.global_error_set.keys()[@intCast(usize, int)];
1026 return (try mod.intern(.{ .err = .{
1027 .ty = ty.toIntern(),
1028 .name = name,
1029 } })).toValue();
16061030 },
16071031 .Pointer => {
1608 assert(!ty.isSlice()); // No well defined layout.
1032 assert(!ty.isSlice(mod)); // No well defined layout.
16091033 return readFromMemory(Type.usize, mod, buffer, arena);
16101034 },
16111035 .Optional => {
1612 assert(ty.isPtrLikeOptional());
1613 var buf: Type.Payload.ElemType = undefined;
1614 const child = ty.optionalChild(&buf);
1036 assert(ty.isPtrLikeOptional(mod));
1037 const child = ty.optionalChild(mod);
16151038 return readFromMemory(child, mod, buffer, arena);
16161039 },
16171040 else => @panic("TODO implement readFromMemory for more types"),
......@@ -1631,7 +1054,7 @@ pub const Value = extern union {
16311054 ) Allocator.Error!Value {
16321055 const target = mod.getTarget();
16331056 const endian = target.cpu.arch.endian();
1634 switch (ty.zigTypeTag()) {
1057 switch (ty.zigTypeTag(mod)) {
16351058 .Void => return Value.void,
16361059 .Bool => {
16371060 const byte = switch (endian) {
......@@ -1644,71 +1067,94 @@ pub const Value = extern union {
16441067 return Value.true;
16451068 }
16461069 },
1647 .Int, .Enum => {
1648 if (buffer.len == 0) return Value.zero;
1649 const int_info = ty.intInfo(target);
1650 const abi_size = @intCast(usize, ty.abiSize(target));
1651
1070 .Int, .Enum => |ty_tag| {
1071 if (buffer.len == 0) return mod.intValue(ty, 0);
1072 const int_info = ty.intInfo(mod);
16521073 const bits = int_info.bits;
1653 if (bits == 0) return Value.zero;
1654 if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
1655 .signed => return Value.Tag.int_i64.create(arena, std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed)),
1656 .unsigned => return Value.Tag.int_u64.create(arena, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)),
1657 } else { // Slow path, we have to construct a big-int
1658 const Limb = std.math.big.Limb;
1659 const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb);
1660 const limbs_buffer = try arena.alloc(Limb, limb_count);
1074 if (bits == 0) return mod.intValue(ty, 0);
16611075
1662 var bigint = BigIntMutable.init(limbs_buffer, 0);
1663 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);
1664 return fromBigInt(arena, bigint.toConst());
1076 // Fast path for integers <= u64
1077 if (bits <= 64) {
1078 const int_ty = switch (ty_tag) {
1079 .Int => ty,
1080 .Enum => ty.intTagType(mod),
1081 else => unreachable,
1082 };
1083 return mod.getCoerced(switch (int_info.signedness) {
1084 .signed => return mod.intValue(
1085 int_ty,
1086 std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed),
1087 ),
1088 .unsigned => return mod.intValue(
1089 int_ty,
1090 std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned),
1091 ),
1092 }, ty);
16651093 }
1666 },
1667 .Float => switch (ty.floatBits(target)) {
1668 16 => return Value.Tag.float_16.create(arena, @bitCast(f16, std.mem.readPackedInt(u16, buffer, bit_offset, endian))),
1669 32 => return Value.Tag.float_32.create(arena, @bitCast(f32, std.mem.readPackedInt(u32, buffer, bit_offset, endian))),
1670 64 => return Value.Tag.float_64.create(arena, @bitCast(f64, std.mem.readPackedInt(u64, buffer, bit_offset, endian))),
1671 80 => return Value.Tag.float_80.create(arena, @bitCast(f80, std.mem.readPackedInt(u80, buffer, bit_offset, endian))),
1672 128 => return Value.Tag.float_128.create(arena, @bitCast(f128, std.mem.readPackedInt(u128, buffer, bit_offset, endian))),
1673 else => unreachable,
1674 },
1094
1095 // Slow path, we have to construct a big-int
1096 const abi_size = @intCast(usize, ty.abiSize(mod));
1097 const Limb = std.math.big.Limb;
1098 const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb);
1099 const limbs_buffer = try arena.alloc(Limb, limb_count);
1100
1101 var bigint = BigIntMutable.init(limbs_buffer, 0);
1102 bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);
1103 return mod.intValue_big(ty, bigint.toConst());
1104 },
1105 .Float => return (try mod.intern(.{ .float = .{
1106 .ty = ty.toIntern(),
1107 .storage = switch (ty.floatBits(target)) {
1108 16 => .{ .f16 = @bitCast(f16, std.mem.readPackedInt(u16, buffer, bit_offset, endian)) },
1109 32 => .{ .f32 = @bitCast(f32, std.mem.readPackedInt(u32, buffer, bit_offset, endian)) },
1110 64 => .{ .f64 = @bitCast(f64, std.mem.readPackedInt(u64, buffer, bit_offset, endian)) },
1111 80 => .{ .f80 = @bitCast(f80, std.mem.readPackedInt(u80, buffer, bit_offset, endian)) },
1112 128 => .{ .f128 = @bitCast(f128, std.mem.readPackedInt(u128, buffer, bit_offset, endian)) },
1113 else => unreachable,
1114 },
1115 } })).toValue(),
16751116 .Vector => {
1676 const elem_ty = ty.childType();
1677 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));
1117 const elem_ty = ty.childType(mod);
1118 const elems = try arena.alloc(InternPool.Index, @intCast(usize, ty.arrayLen(mod)));
16781119
16791120 var bits: u16 = 0;
1680 const elem_bit_size = @intCast(u16, elem_ty.bitSize(target));
1121 const elem_bit_size = @intCast(u16, elem_ty.bitSize(mod));
16811122 for (elems, 0..) |_, i| {
16821123 // On big-endian systems, LLVM reverses the element order of vectors by default
16831124 const tgt_elem_i = if (endian == .Big) elems.len - i - 1 else i;
1684 elems[tgt_elem_i] = try readFromPackedMemory(elem_ty, mod, buffer, bit_offset + bits, arena);
1125 elems[tgt_elem_i] = try (try readFromPackedMemory(elem_ty, mod, buffer, bit_offset + bits, arena)).intern(elem_ty, mod);
16851126 bits += elem_bit_size;
16861127 }
1687 return Tag.aggregate.create(arena, elems);
1128 return (try mod.intern(.{ .aggregate = .{
1129 .ty = ty.toIntern(),
1130 .storage = .{ .elems = elems },
1131 } })).toValue();
16881132 },
1689 .Struct => switch (ty.containerLayout()) {
1133 .Struct => switch (ty.containerLayout(mod)) {
16901134 .Auto => unreachable, // Sema is supposed to have emitted a compile error already
16911135 .Extern => unreachable, // Handled by non-packed readFromMemory
16921136 .Packed => {
16931137 var bits: u16 = 0;
1694 const fields = ty.structFields().values();
1695 const field_vals = try arena.alloc(Value, fields.len);
1138 const fields = ty.structFields(mod).values();
1139 const field_vals = try arena.alloc(InternPool.Index, fields.len);
16961140 for (fields, 0..) |field, i| {
1697 const field_bits = @intCast(u16, field.ty.bitSize(target));
1698 field_vals[i] = try readFromPackedMemory(field.ty, mod, buffer, bit_offset + bits, arena);
1141 const field_bits = @intCast(u16, field.ty.bitSize(mod));
1142 field_vals[i] = try (try readFromPackedMemory(field.ty, mod, buffer, bit_offset + bits, arena)).intern(field.ty, mod);
16991143 bits += field_bits;
17001144 }
1701 return Tag.aggregate.create(arena, field_vals);
1145 return (try mod.intern(.{ .aggregate = .{
1146 .ty = ty.toIntern(),
1147 .storage = .{ .elems = field_vals },
1148 } })).toValue();
17021149 },
17031150 },
17041151 .Pointer => {
1705 assert(!ty.isSlice()); // No well defined layout.
1152 assert(!ty.isSlice(mod)); // No well defined layout.
17061153 return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena);
17071154 },
17081155 .Optional => {
1709 assert(ty.isPtrLikeOptional());
1710 var buf: Type.Payload.ElemType = undefined;
1711 const child = ty.optionalChild(&buf);
1156 assert(ty.isPtrLikeOptional(mod));
1157 const child = ty.optionalChild(mod);
17121158 return readFromPackedMemory(child, mod, buffer, bit_offset, arena);
17131159 },
17141160 else => @panic("TODO implement readFromPackedMemory for more types"),
......@@ -1716,31 +1162,22 @@ pub const Value = extern union {
17161162 }
17171163
17181164 /// Asserts that the value is a float or an integer.
1719 pub fn toFloat(val: Value, comptime T: type) T {
1720 return switch (val.tag()) {
1721 .float_16 => @floatCast(T, val.castTag(.float_16).?.data),
1722 .float_32 => @floatCast(T, val.castTag(.float_32).?.data),
1723 .float_64 => @floatCast(T, val.castTag(.float_64).?.data),
1724 .float_80 => @floatCast(T, val.castTag(.float_80).?.data),
1725 .float_128 => @floatCast(T, val.castTag(.float_128).?.data),
1726
1727 .zero => 0,
1728 .one => 1,
1729 .int_u64 => {
1730 if (T == f80) {
1731 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1732 }
1733 return @intToFloat(T, val.castTag(.int_u64).?.data);
1165 pub fn toFloat(val: Value, comptime T: type, mod: *Module) T {
1166 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1167 .int => |int| switch (int.storage) {
1168 .big_int => |big_int| @floatCast(T, bigIntToFloat(big_int.limbs, big_int.positive)),
1169 inline .u64, .i64 => |x| {
1170 if (T == f80) {
1171 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1172 }
1173 return @intToFloat(T, x);
1174 },
1175 .lazy_align => |ty| @intToFloat(T, ty.toType().abiAlignment(mod)),
1176 .lazy_size => |ty| @intToFloat(T, ty.toType().abiSize(mod)),
17341177 },
1735 .int_i64 => {
1736 if (T == f80) {
1737 @panic("TODO we can't lower this properly on non-x86 llvm backend yet");
1738 }
1739 return @intToFloat(T, val.castTag(.int_i64).?.data);
1178 .float => |float| switch (float.storage) {
1179 inline else => |x| @floatCast(T, x),
17401180 },
1741
1742 .int_big_positive => @floatCast(T, bigIntToFloat(val.castTag(.int_big_positive).?.data, true)),
1743 .int_big_negative => @floatCast(T, bigIntToFloat(val.castTag(.int_big_negative).?.data, false)),
17441181 else => unreachable,
17451182 };
17461183 }
......@@ -1764,103 +1201,29 @@ pub const Value = extern union {
17641201 }
17651202 }
17661203
1767 pub fn clz(val: Value, ty: Type, target: Target) u64 {
1768 const ty_bits = ty.intInfo(target).bits;
1769 switch (val.tag()) {
1770 .zero, .bool_false => return ty_bits,
1771 .one, .bool_true => return ty_bits - 1,
1772
1773 .int_u64 => {
1774 const big = @clz(val.castTag(.int_u64).?.data);
1775 return big + ty_bits - 64;
1776 },
1777 .int_i64 => {
1778 @panic("TODO implement i64 Value clz");
1779 },
1780 .int_big_positive => {
1781 const bigint = val.castTag(.int_big_positive).?.asBigInt();
1782 return bigint.clz(ty_bits);
1783 },
1784 .int_big_negative => {
1785 @panic("TODO implement int_big_negative Value clz");
1786 },
1787
1788 .the_only_possible_value => {
1789 assert(ty_bits == 0);
1790 return ty_bits;
1791 },
1792
1793 .lazy_align, .lazy_size => {
1794 var bigint_buf: BigIntSpace = undefined;
1795 const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable;
1796 return bigint.clz(ty_bits);
1797 },
1798
1799 else => unreachable,
1800 }
1204 pub fn clz(val: Value, ty: Type, mod: *Module) u64 {
1205 var bigint_buf: BigIntSpace = undefined;
1206 const bigint = val.toBigInt(&bigint_buf, mod);
1207 return bigint.clz(ty.intInfo(mod).bits);
18011208 }
18021209
1803 pub fn ctz(val: Value, ty: Type, target: Target) u64 {
1804 const ty_bits = ty.intInfo(target).bits;
1805 switch (val.tag()) {
1806 .zero, .bool_false => return ty_bits,
1807 .one, .bool_true => return 0,
1808
1809 .int_u64 => {
1810 const big = @ctz(val.castTag(.int_u64).?.data);
1811 return if (big == 64) ty_bits else big;
1812 },
1813 .int_i64 => {
1814 @panic("TODO implement i64 Value ctz");
1815 },
1816 .int_big_positive => {
1817 const bigint = val.castTag(.int_big_positive).?.asBigInt();
1818 return bigint.ctz();
1819 },
1820 .int_big_negative => {
1821 @panic("TODO implement int_big_negative Value ctz");
1822 },
1823
1824 .the_only_possible_value => {
1825 assert(ty_bits == 0);
1826 return ty_bits;
1827 },
1828
1829 .lazy_align, .lazy_size => {
1830 var bigint_buf: BigIntSpace = undefined;
1831 const bigint = val.toBigIntAdvanced(&bigint_buf, target, null) catch unreachable;
1832 return bigint.ctz();
1833 },
1834
1835 else => unreachable,
1836 }
1210 pub fn ctz(val: Value, ty: Type, mod: *Module) u64 {
1211 var bigint_buf: BigIntSpace = undefined;
1212 const bigint = val.toBigInt(&bigint_buf, mod);
1213 return bigint.ctz(ty.intInfo(mod).bits);
18371214 }
18381215
1839 pub fn popCount(val: Value, ty: Type, target: Target) u64 {
1840 assert(!val.isUndef());
1841 switch (val.tag()) {
1842 .zero, .bool_false => return 0,
1843 .one, .bool_true => return 1,
1844
1845 .int_u64 => return @popCount(val.castTag(.int_u64).?.data),
1846
1847 else => {
1848 const info = ty.intInfo(target);
1849
1850 var buffer: Value.BigIntSpace = undefined;
1851 const int = val.toBigInt(&buffer, target);
1852 return @intCast(u64, int.popCount(info.bits));
1853 },
1854 }
1216 pub fn popCount(val: Value, ty: Type, mod: *Module) u64 {
1217 var bigint_buf: BigIntSpace = undefined;
1218 const bigint = val.toBigInt(&bigint_buf, mod);
1219 return @intCast(u64, bigint.popCount(ty.intInfo(mod).bits));
18551220 }
18561221
1857 pub fn bitReverse(val: Value, ty: Type, target: Target, arena: Allocator) !Value {
1858 assert(!val.isUndef());
1859
1860 const info = ty.intInfo(target);
1222 pub fn bitReverse(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1223 const info = ty.intInfo(mod);
18611224
18621225 var buffer: Value.BigIntSpace = undefined;
1863 const operand_bigint = val.toBigInt(&buffer, target);
1226 const operand_bigint = val.toBigInt(&buffer, mod);
18641227
18651228 const limbs = try arena.alloc(
18661229 std.math.big.Limb,
......@@ -1869,19 +1232,17 @@ pub const Value = extern union {
18691232 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
18701233 result_bigint.bitReverse(operand_bigint, info.signedness, info.bits);
18711234
1872 return fromBigInt(arena, result_bigint.toConst());
1235 return mod.intValue_big(ty, result_bigint.toConst());
18731236 }
18741237
1875 pub fn byteSwap(val: Value, ty: Type, target: Target, arena: Allocator) !Value {
1876 assert(!val.isUndef());
1877
1878 const info = ty.intInfo(target);
1238 pub fn byteSwap(val: Value, ty: Type, mod: *Module, arena: Allocator) !Value {
1239 const info = ty.intInfo(mod);
18791240
18801241 // Bit count must be evenly divisible by 8
18811242 assert(info.bits % 8 == 0);
18821243
18831244 var buffer: Value.BigIntSpace = undefined;
1884 const operand_bigint = val.toBigInt(&buffer, target);
1245 const operand_bigint = val.toBigInt(&buffer, mod);
18851246
18861247 const limbs = try arena.alloc(
18871248 std.math.big.Limb,
......@@ -1890,176 +1251,98 @@ pub const Value = extern union {
18901251 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
18911252 result_bigint.byteSwap(operand_bigint, info.signedness, info.bits / 8);
18921253
1893 return fromBigInt(arena, result_bigint.toConst());
1254 return mod.intValue_big(ty, result_bigint.toConst());
18941255 }
18951256
18961257 /// Asserts the value is an integer and not undefined.
18971258 /// Returns the number of bits the value requires to represent stored in twos complement form.
1898 pub fn intBitCountTwosComp(self: Value, target: Target) usize {
1899 switch (self.tag()) {
1900 .zero,
1901 .bool_false,
1902 .the_only_possible_value,
1903 => return 0,
1904
1905 .one,
1906 .bool_true,
1907 => return 1,
1908
1909 .int_u64 => {
1910 const x = self.castTag(.int_u64).?.data;
1911 if (x == 0) return 0;
1912 return @intCast(usize, std.math.log2(x) + 1);
1913 },
1914 .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(),
1915 .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(),
1916
1917 .decl_ref_mut,
1918 .comptime_field_ptr,
1919 .extern_fn,
1920 .decl_ref,
1921 .function,
1922 .variable,
1923 .eu_payload_ptr,
1924 .opt_payload_ptr,
1925 => return target.ptrBitWidth(),
1926
1927 else => {
1928 var buffer: BigIntSpace = undefined;
1929 return self.toBigInt(&buffer, target).bitCountTwosComp();
1930 },
1931 }
1259 pub fn intBitCountTwosComp(self: Value, mod: *Module) usize {
1260 var buffer: BigIntSpace = undefined;
1261 const big_int = self.toBigInt(&buffer, mod);
1262 return big_int.bitCountTwosComp();
19321263 }
19331264
19341265 /// Converts an integer or a float to a float. May result in a loss of information.
19351266 /// Caller can find out by equality checking the result against the operand.
1936 pub fn floatCast(self: Value, arena: Allocator, dest_ty: Type, target: Target) !Value {
1937 switch (dest_ty.floatBits(target)) {
1938 16 => return Value.Tag.float_16.create(arena, self.toFloat(f16)),
1939 32 => return Value.Tag.float_32.create(arena, self.toFloat(f32)),
1940 64 => return Value.Tag.float_64.create(arena, self.toFloat(f64)),
1941 80 => return Value.Tag.float_80.create(arena, self.toFloat(f80)),
1942 128 => return Value.Tag.float_128.create(arena, self.toFloat(f128)),
1943 else => unreachable,
1944 }
1267 pub fn floatCast(self: Value, dest_ty: Type, mod: *Module) !Value {
1268 const target = mod.getTarget();
1269 return (try mod.intern(.{ .float = .{
1270 .ty = dest_ty.toIntern(),
1271 .storage = switch (dest_ty.floatBits(target)) {
1272 16 => .{ .f16 = self.toFloat(f16, mod) },
1273 32 => .{ .f32 = self.toFloat(f32, mod) },
1274 64 => .{ .f64 = self.toFloat(f64, mod) },
1275 80 => .{ .f80 = self.toFloat(f80, mod) },
1276 128 => .{ .f128 = self.toFloat(f128, mod) },
1277 else => unreachable,
1278 },
1279 } })).toValue();
19451280 }
19461281
19471282 /// Asserts the value is a float
1948 pub fn floatHasFraction(self: Value) bool {
1949 return switch (self.tag()) {
1950 .zero,
1951 .one,
1952 => false,
1953
1954 .float_16 => @rem(self.castTag(.float_16).?.data, 1) != 0,
1955 .float_32 => @rem(self.castTag(.float_32).?.data, 1) != 0,
1956 .float_64 => @rem(self.castTag(.float_64).?.data, 1) != 0,
1957 //.float_80 => @rem(self.castTag(.float_80).?.data, 1) != 0,
1958 .float_80 => @panic("TODO implement __remx in compiler-rt"),
1959 .float_128 => @rem(self.castTag(.float_128).?.data, 1) != 0,
1960
1283 pub fn floatHasFraction(self: Value, mod: *const Module) bool {
1284 return switch (mod.intern_pool.indexToKey(self.toIntern())) {
1285 .float => |float| switch (float.storage) {
1286 inline else => |x| @rem(x, 1) != 0,
1287 },
19611288 else => unreachable,
19621289 };
19631290 }
19641291
1965 pub fn orderAgainstZero(lhs: Value) std.math.Order {
1966 return orderAgainstZeroAdvanced(lhs, null) catch unreachable;
1292 pub fn orderAgainstZero(lhs: Value, mod: *Module) std.math.Order {
1293 return orderAgainstZeroAdvanced(lhs, mod, null) catch unreachable;
19671294 }
19681295
19691296 pub fn orderAgainstZeroAdvanced(
19701297 lhs: Value,
1298 mod: *Module,
19711299 opt_sema: ?*Sema,
19721300 ) Module.CompileError!std.math.Order {
1973 return switch (lhs.tag()) {
1974 .zero,
1975 .bool_false,
1976 .the_only_possible_value,
1977 => .eq,
1978
1979 .one,
1980 .bool_true,
1981 .decl_ref,
1982 .decl_ref_mut,
1983 .comptime_field_ptr,
1984 .extern_fn,
1985 .function,
1986 .variable,
1987 => .gt,
1988
1989 .enum_field_index => return std.math.order(lhs.castTag(.enum_field_index).?.data, 0),
1990 .runtime_value => {
1991 // This is needed to correctly handle hashing the value.
1992 // Checks in Sema should prevent direct comparisons from reaching here.
1993 const val = lhs.castTag(.runtime_value).?.data;
1994 return val.orderAgainstZeroAdvanced(opt_sema);
1995 },
1996 .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0),
1997 .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0),
1998 .int_big_positive => lhs.castTag(.int_big_positive).?.asBigInt().orderAgainstScalar(0),
1999 .int_big_negative => lhs.castTag(.int_big_negative).?.asBigInt().orderAgainstScalar(0),
2000
2001 .lazy_align => {
2002 const ty = lhs.castTag(.lazy_align).?.data;
2003 const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
2004 if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
2005 error.NeedLazy => unreachable,
2006 else => |e| return e,
2007 }) {
2008 return .gt;
2009 } else {
2010 return .eq;
2011 }
2012 },
2013 .lazy_size => {
2014 const ty = lhs.castTag(.lazy_size).?.data;
2015 const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager;
2016 if (ty.hasRuntimeBitsAdvanced(false, strat) catch |err| switch (err) {
2017 error.NeedLazy => unreachable,
2018 else => |e| return e,
2019 }) {
2020 return .gt;
2021 } else {
2022 return .eq;
2023 }
2024 },
2025
2026 .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0),
2027 .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0),
2028 .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0),
2029 .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0),
2030 .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0),
2031
2032 .elem_ptr => {
2033 const elem_ptr = lhs.castTag(.elem_ptr).?.data;
2034 switch (try elem_ptr.array_ptr.orderAgainstZeroAdvanced(opt_sema)) {
2035 .lt => unreachable,
2036 .gt => return .gt,
2037 .eq => {
2038 if (elem_ptr.index == 0) {
2039 return .eq;
2040 } else {
2041 return .gt;
2042 }
1301 return switch (lhs.toIntern()) {
1302 .bool_false => .eq,
1303 .bool_true => .gt,
1304 else => switch (mod.intern_pool.indexToKey(lhs.toIntern())) {
1305 .ptr => |ptr| switch (ptr.addr) {
1306 .decl, .mut_decl, .comptime_field => .gt,
1307 .int => |int| int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
1308 .elem => |elem| switch (try elem.base.toValue().orderAgainstZeroAdvanced(mod, opt_sema)) {
1309 .lt => unreachable,
1310 .gt => .gt,
1311 .eq => if (elem.index == 0) .eq else .gt,
20431312 },
2044 }
1313 else => unreachable,
1314 },
1315 .int => |int| switch (int.storage) {
1316 .big_int => |big_int| big_int.orderAgainstScalar(0),
1317 inline .u64, .i64 => |x| std.math.order(x, 0),
1318 .lazy_align, .lazy_size => |ty| return if (ty.toType().hasRuntimeBitsAdvanced(
1319 mod,
1320 false,
1321 if (opt_sema) |sema| .{ .sema = sema } else .eager,
1322 ) catch |err| switch (err) {
1323 error.NeedLazy => unreachable,
1324 else => |e| return e,
1325 }) .gt else .eq,
1326 },
1327 .enum_tag => |enum_tag| enum_tag.int.toValue().orderAgainstZeroAdvanced(mod, opt_sema),
1328 .float => |float| switch (float.storage) {
1329 inline else => |x| std.math.order(x, 0),
1330 },
1331 else => unreachable,
20451332 },
2046
2047 else => unreachable,
20481333 };
20491334 }
20501335
20511336 /// Asserts the value is comparable.
2052 pub fn order(lhs: Value, rhs: Value, target: Target) std.math.Order {
2053 return orderAdvanced(lhs, rhs, target, null) catch unreachable;
1337 pub fn order(lhs: Value, rhs: Value, mod: *Module) std.math.Order {
1338 return orderAdvanced(lhs, rhs, mod, null) catch unreachable;
20541339 }
20551340
20561341 /// Asserts the value is comparable.
20571342 /// If opt_sema is null then this function asserts things are resolved and cannot fail.
2058 pub fn orderAdvanced(lhs: Value, rhs: Value, target: Target, opt_sema: ?*Sema) !std.math.Order {
2059 const lhs_tag = lhs.tag();
2060 const rhs_tag = rhs.tag();
2061 const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(opt_sema);
2062 const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(opt_sema);
1343 pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, opt_sema: ?*Sema) !std.math.Order {
1344 const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, opt_sema);
1345 const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, opt_sema);
20631346 switch (lhs_against_zero) {
20641347 .lt => if (rhs_against_zero != .lt) return .lt,
20651348 .eq => return rhs_against_zero.invert(),
......@@ -2071,48 +1354,34 @@ pub const Value = extern union {
20711354 .gt => {},
20721355 }
20731356
2074 const lhs_float = lhs.isFloat();
2075 const rhs_float = rhs.isFloat();
2076 if (lhs_float and rhs_float) {
2077 if (lhs_tag == rhs_tag) {
2078 return switch (lhs.tag()) {
2079 .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
2080 .float_32 => return std.math.order(lhs.castTag(.float_32).?.data, rhs.castTag(.float_32).?.data),
2081 .float_64 => return std.math.order(lhs.castTag(.float_64).?.data, rhs.castTag(.float_64).?.data),
2082 .float_80 => return std.math.order(lhs.castTag(.float_80).?.data, rhs.castTag(.float_80).?.data),
2083 .float_128 => return std.math.order(lhs.castTag(.float_128).?.data, rhs.castTag(.float_128).?.data),
2084 else => unreachable,
2085 };
2086 }
2087 }
2088 if (lhs_float or rhs_float) {
2089 const lhs_f128 = lhs.toFloat(f128);
2090 const rhs_f128 = rhs.toFloat(f128);
1357 if (lhs.isFloat(mod) or rhs.isFloat(mod)) {
1358 const lhs_f128 = lhs.toFloat(f128, mod);
1359 const rhs_f128 = rhs.toFloat(f128, mod);
20911360 return std.math.order(lhs_f128, rhs_f128);
20921361 }
20931362
20941363 var lhs_bigint_space: BigIntSpace = undefined;
20951364 var rhs_bigint_space: BigIntSpace = undefined;
2096 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, target, opt_sema);
2097 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, target, opt_sema);
1365 const lhs_bigint = try lhs.toBigIntAdvanced(&lhs_bigint_space, mod, opt_sema);
1366 const rhs_bigint = try rhs.toBigIntAdvanced(&rhs_bigint_space, mod, opt_sema);
20981367 return lhs_bigint.order(rhs_bigint);
20991368 }
21001369
21011370 /// Asserts the value is comparable. Does not take a type parameter because it supports
21021371 /// comparisons between heterogeneous types.
2103 pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, target: Target) bool {
2104 return compareHeteroAdvanced(lhs, op, rhs, target, null) catch unreachable;
1372 pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *Module) bool {
1373 return compareHeteroAdvanced(lhs, op, rhs, mod, null) catch unreachable;
21051374 }
21061375
21071376 pub fn compareHeteroAdvanced(
21081377 lhs: Value,
21091378 op: std.math.CompareOperator,
21101379 rhs: Value,
2111 target: Target,
1380 mod: *Module,
21121381 opt_sema: ?*Sema,
21131382 ) !bool {
2114 if (lhs.pointerDecl()) |lhs_decl| {
2115 if (rhs.pointerDecl()) |rhs_decl| {
1383 if (lhs.pointerDecl(mod)) |lhs_decl| {
1384 if (rhs.pointerDecl(mod)) |rhs_decl| {
21161385 switch (op) {
21171386 .eq => return lhs_decl == rhs_decl,
21181387 .neq => return lhs_decl != rhs_decl,
......@@ -2125,27 +1394,25 @@ pub const Value = extern union {
21251394 else => {},
21261395 }
21271396 }
2128 } else if (rhs.pointerDecl()) |_| {
1397 } else if (rhs.pointerDecl(mod)) |_| {
21291398 switch (op) {
21301399 .eq => return false,
21311400 .neq => return true,
21321401 else => {},
21331402 }
21341403 }
2135 return (try orderAdvanced(lhs, rhs, target, opt_sema)).compare(op);
1404 return (try orderAdvanced(lhs, rhs, mod, opt_sema)).compare(op);
21361405 }
21371406
21381407 /// Asserts the values are comparable. Both operands have type `ty`.
21391408 /// For vectors, returns true if comparison is true for ALL elements.
2140 pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {
2141 if (ty.zigTypeTag() == .Vector) {
2142 var i: usize = 0;
2143 while (i < ty.vectorLen()) : (i += 1) {
2144 var lhs_buf: Value.ElemValueBuffer = undefined;
2145 var rhs_buf: Value.ElemValueBuffer = undefined;
2146 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
2147 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
2148 if (!compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(), mod)) {
1409 pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) !bool {
1410 if (ty.zigTypeTag(mod) == .Vector) {
1411 const scalar_ty = ty.scalarType(mod);
1412 for (0..ty.vectorLen(mod)) |i| {
1413 const lhs_elem = try lhs.elemValue(mod, i);
1414 const rhs_elem = try rhs.elemValue(mod, i);
1415 if (!compareScalar(lhs_elem, op, rhs_elem, scalar_ty, mod)) {
21491416 return false;
21501417 }
21511418 }
......@@ -2165,7 +1432,7 @@ pub const Value = extern union {
21651432 return switch (op) {
21661433 .eq => lhs.eql(rhs, ty, mod),
21671434 .neq => !lhs.eql(rhs, ty, mod),
2168 else => compareHetero(lhs, op, rhs, mod.getTarget()),
1435 else => compareHetero(lhs, op, rhs, mod),
21691436 };
21701437 }
21711438
......@@ -2191,47 +1458,31 @@ pub const Value = extern union {
21911458 mod: *Module,
21921459 opt_sema: ?*Sema,
21931460 ) Module.CompileError!bool {
2194 if (lhs.isInf()) {
1461 if (lhs.isInf(mod)) {
21951462 switch (op) {
21961463 .neq => return true,
21971464 .eq => return false,
2198 .gt, .gte => return !lhs.isNegativeInf(),
2199 .lt, .lte => return lhs.isNegativeInf(),
1465 .gt, .gte => return !lhs.isNegativeInf(mod),
1466 .lt, .lte => return lhs.isNegativeInf(mod),
22001467 }
22011468 }
22021469
2203 switch (lhs.tag()) {
2204 .repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
2205 .aggregate => {
2206 for (lhs.castTag(.aggregate).?.data) |elem_val| {
2207 if (!(try elem_val.compareAllWithZeroAdvancedExtra(op, mod, opt_sema))) return false;
2208 }
2209 return true;
1470 switch (mod.intern_pool.indexToKey(lhs.toIntern())) {
1471 .float => |float| switch (float.storage) {
1472 inline else => |x| if (std.math.isNan(x)) return op == .neq,
22101473 },
2211 .empty_array => return true,
2212 .str_lit => {
2213 const str_lit = lhs.castTag(.str_lit).?.data;
2214 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
2215 for (bytes) |byte| {
2216 if (!std.math.compare(byte, op, 0)) return false;
2217 }
2218 return true;
2219 },
2220 .bytes => {
2221 const bytes = lhs.castTag(.bytes).?.data;
2222 for (bytes) |byte| {
2223 if (!std.math.compare(byte, op, 0)) return false;
2224 }
2225 return true;
1474 .aggregate => |aggregate| return switch (aggregate.storage) {
1475 .bytes => |bytes| for (bytes) |byte| {
1476 if (!std.math.order(byte, 0).compare(op)) break false;
1477 } else true,
1478 .elems => |elems| for (elems) |elem| {
1479 if (!try elem.toValue().compareAllWithZeroAdvancedExtra(op, mod, opt_sema)) break false;
1480 } else true,
1481 .repeated_elem => |elem| elem.toValue().compareAllWithZeroAdvancedExtra(op, mod, opt_sema),
22261482 },
2227 .float_16 => if (std.math.isNan(lhs.castTag(.float_16).?.data)) return op == .neq,
2228 .float_32 => if (std.math.isNan(lhs.castTag(.float_32).?.data)) return op == .neq,
2229 .float_64 => if (std.math.isNan(lhs.castTag(.float_64).?.data)) return op == .neq,
2230 .float_80 => if (std.math.isNan(lhs.castTag(.float_80).?.data)) return op == .neq,
2231 .float_128 => if (std.math.isNan(lhs.castTag(.float_128).?.data)) return op == .neq,
22321483 else => {},
22331484 }
2234 return (try orderAgainstZeroAdvanced(lhs, opt_sema)).compare(op);
1485 return (try orderAgainstZeroAdvanced(lhs, mod, opt_sema)).compare(op);
22351486 }
22361487
22371488 pub fn eql(a: Value, b: Value, ty: Type, mod: *Module) bool {
......@@ -2255,109 +1506,42 @@ pub const Value = extern union {
22551506 mod: *Module,
22561507 opt_sema: ?*Sema,
22571508 ) Module.CompileError!bool {
1509 if (a.ip_index != .none or b.ip_index != .none) return a.ip_index == b.ip_index;
1510
22581511 const target = mod.getTarget();
22591512 const a_tag = a.tag();
22601513 const b_tag = b.tag();
22611514 if (a_tag == b_tag) switch (a_tag) {
2262 .undef => return true,
2263 .void_value, .null_value, .the_only_possible_value, .empty_struct_value => return true,
2264 .enum_literal => {
2265 const a_name = a.castTag(.enum_literal).?.data;
2266 const b_name = b.castTag(.enum_literal).?.data;
2267 return std.mem.eql(u8, a_name, b_name);
2268 },
2269 .enum_field_index => {
2270 const a_field_index = a.castTag(.enum_field_index).?.data;
2271 const b_field_index = b.castTag(.enum_field_index).?.data;
2272 return a_field_index == b_field_index;
2273 },
2274 .opt_payload => {
2275 const a_payload = a.castTag(.opt_payload).?.data;
2276 const b_payload = b.castTag(.opt_payload).?.data;
2277 var buffer: Type.Payload.ElemType = undefined;
2278 const payload_ty = ty.optionalChild(&buffer);
2279 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
2280 },
2281 .slice => {
2282 const a_payload = a.castTag(.slice).?.data;
2283 const b_payload = b.castTag(.slice).?.data;
2284 if (!(try eqlAdvanced(a_payload.len, Type.usize, b_payload.len, Type.usize, mod, opt_sema))) {
2285 return false;
2286 }
2287
2288 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2289 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);
2290
2291 return eqlAdvanced(a_payload.ptr, ptr_ty, b_payload.ptr, ptr_ty, mod, opt_sema);
2292 },
2293 .elem_ptr => {
2294 const a_payload = a.castTag(.elem_ptr).?.data;
2295 const b_payload = b.castTag(.elem_ptr).?.data;
2296 if (a_payload.index != b_payload.index) return false;
2297
2298 return eqlAdvanced(a_payload.array_ptr, ty, b_payload.array_ptr, ty, mod, opt_sema);
2299 },
2300 .field_ptr => {
2301 const a_payload = a.castTag(.field_ptr).?.data;
2302 const b_payload = b.castTag(.field_ptr).?.data;
2303 if (a_payload.field_index != b_payload.field_index) return false;
2304
2305 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
2306 },
2307 .@"error" => {
2308 const a_name = a.castTag(.@"error").?.data.name;
2309 const b_name = b.castTag(.@"error").?.data.name;
2310 return std.mem.eql(u8, a_name, b_name);
2311 },
2312 .eu_payload => {
2313 const a_payload = a.castTag(.eu_payload).?.data;
2314 const b_payload = b.castTag(.eu_payload).?.data;
2315 const payload_ty = ty.errorUnionPayload();
2316 return eqlAdvanced(a_payload, payload_ty, b_payload, payload_ty, mod, opt_sema);
2317 },
2318 .eu_payload_ptr => {
2319 const a_payload = a.castTag(.eu_payload_ptr).?.data;
2320 const b_payload = b.castTag(.eu_payload_ptr).?.data;
2321 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
2322 },
2323 .opt_payload_ptr => {
2324 const a_payload = a.castTag(.opt_payload_ptr).?.data;
2325 const b_payload = b.castTag(.opt_payload_ptr).?.data;
2326 return eqlAdvanced(a_payload.container_ptr, ty, b_payload.container_ptr, ty, mod, opt_sema);
2327 },
2328 .function => {
2329 const a_payload = a.castTag(.function).?.data;
2330 const b_payload = b.castTag(.function).?.data;
2331 return a_payload == b_payload;
2332 },
23331515 .aggregate => {
23341516 const a_field_vals = a.castTag(.aggregate).?.data;
23351517 const b_field_vals = b.castTag(.aggregate).?.data;
23361518 assert(a_field_vals.len == b_field_vals.len);
23371519
2338 if (ty.isSimpleTupleOrAnonStruct()) {
2339 const types = ty.tupleFields().types;
2340 assert(types.len == a_field_vals.len);
2341 for (types, 0..) |field_ty, i| {
2342 if (!(try eqlAdvanced(a_field_vals[i], field_ty, b_field_vals[i], field_ty, mod, opt_sema))) {
2343 return false;
1520 switch (mod.intern_pool.indexToKey(ty.toIntern())) {
1521 .anon_struct_type => |anon_struct| {
1522 assert(anon_struct.types.len == a_field_vals.len);
1523 for (anon_struct.types, 0..) |field_ty, i| {
1524 if (!(try eqlAdvanced(a_field_vals[i], field_ty.toType(), b_field_vals[i], field_ty.toType(), mod, opt_sema))) {
1525 return false;
1526 }
23441527 }
2345 }
2346 return true;
2347 }
2348
2349 if (ty.zigTypeTag() == .Struct) {
2350 const fields = ty.structFields().values();
2351 assert(fields.len == a_field_vals.len);
2352 for (fields, 0..) |field, i| {
2353 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
2354 return false;
1528 return true;
1529 },
1530 .struct_type => |struct_type| {
1531 const struct_obj = mod.structPtrUnwrap(struct_type.index).?;
1532 const fields = struct_obj.fields.values();
1533 assert(fields.len == a_field_vals.len);
1534 for (fields, 0..) |field, i| {
1535 if (!(try eqlAdvanced(a_field_vals[i], field.ty, b_field_vals[i], field.ty, mod, opt_sema))) {
1536 return false;
1537 }
23551538 }
2356 }
2357 return true;
1539 return true;
1540 },
1541 else => {},
23581542 }
23591543
2360 const elem_ty = ty.childType();
1544 const elem_ty = ty.childType(mod);
23611545 for (a_field_vals, 0..) |a_elem, i| {
23621546 const b_elem = b_field_vals[i];
23631547
......@@ -2370,9 +1554,9 @@ pub const Value = extern union {
23701554 .@"union" => {
23711555 const a_union = a.castTag(.@"union").?.data;
23721556 const b_union = b.castTag(.@"union").?.data;
2373 switch (ty.containerLayout()) {
1557 switch (ty.containerLayout(mod)) {
23741558 .Packed, .Extern => {
2375 const tag_ty = ty.unionTagTypeHypothetical();
1559 const tag_ty = ty.unionTagTypeHypothetical(mod);
23761560 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {
23771561 // In this case, we must disregard mismatching tags and compare
23781562 // based on the in-memory bytes of the payloads.
......@@ -2380,7 +1564,7 @@ pub const Value = extern union {
23801564 }
23811565 },
23821566 .Auto => {
2383 const tag_ty = ty.unionTagTypeHypothetical();
1567 const tag_ty = ty.unionTagTypeHypothetical(mod);
23841568 if (!(try eqlAdvanced(a_union.tag, tag_ty, b_union.tag, tag_ty, mod, opt_sema))) {
23851569 return false;
23861570 }
......@@ -2390,122 +1574,91 @@ pub const Value = extern union {
23901574 return eqlAdvanced(a_union.val, active_field_ty, b_union.val, active_field_ty, mod, opt_sema);
23911575 },
23921576 else => {},
2393 } else if (b_tag == .null_value or b_tag == .@"error") {
2394 return false;
2395 } else if (a_tag == .undef or b_tag == .undef) {
2396 return false;
2397 }
1577 };
23981578
2399 if (a.pointerDecl()) |a_decl| {
2400 if (b.pointerDecl()) |b_decl| {
1579 if (a.pointerDecl(mod)) |a_decl| {
1580 if (b.pointerDecl(mod)) |b_decl| {
24011581 return a_decl == b_decl;
24021582 } else {
24031583 return false;
24041584 }
2405 } else if (b.pointerDecl()) |_| {
1585 } else if (b.pointerDecl(mod)) |_| {
24061586 return false;
24071587 }
24081588
2409 switch (ty.zigTypeTag()) {
1589 switch (ty.zigTypeTag(mod)) {
24101590 .Type => {
2411 var buf_a: ToTypeBuffer = undefined;
2412 var buf_b: ToTypeBuffer = undefined;
2413 const a_type = a.toType(&buf_a);
2414 const b_type = b.toType(&buf_b);
1591 const a_type = a.toType();
1592 const b_type = b.toType();
24151593 return a_type.eql(b_type, mod);
24161594 },
24171595 .Enum => {
2418 var buf_a: Payload.U64 = undefined;
2419 var buf_b: Payload.U64 = undefined;
2420 const a_val = a.enumToInt(ty, &buf_a);
2421 const b_val = b.enumToInt(ty, &buf_b);
2422 var buf_ty: Type.Payload.Bits = undefined;
2423 const int_ty = ty.intTagType(&buf_ty);
1596 const a_val = try a.enumToInt(ty, mod);
1597 const b_val = try b.enumToInt(ty, mod);
1598 const int_ty = ty.intTagType(mod);
24241599 return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema);
24251600 },
24261601 .Array, .Vector => {
2427 const len = ty.arrayLen();
2428 const elem_ty = ty.childType();
1602 const len = ty.arrayLen(mod);
1603 const elem_ty = ty.childType(mod);
24291604 var i: usize = 0;
2430 var a_buf: ElemValueBuffer = undefined;
2431 var b_buf: ElemValueBuffer = undefined;
24321605 while (i < len) : (i += 1) {
2433 const a_elem = elemValueBuffer(a, mod, i, &a_buf);
2434 const b_elem = elemValueBuffer(b, mod, i, &b_buf);
1606 const a_elem = try elemValue(a, mod, i);
1607 const b_elem = try elemValue(b, mod, i);
24351608 if (!(try eqlAdvanced(a_elem, elem_ty, b_elem, elem_ty, mod, opt_sema))) {
24361609 return false;
24371610 }
24381611 }
24391612 return true;
24401613 },
2441 .Pointer => switch (ty.ptrSize()) {
1614 .Pointer => switch (ty.ptrSize(mod)) {
24421615 .Slice => {
2443 const a_len = switch (a_ty.ptrSize()) {
1616 const a_len = switch (a_ty.ptrSize(mod)) {
24441617 .Slice => a.sliceLen(mod),
2445 .One => a_ty.childType().arrayLen(),
1618 .One => a_ty.childType(mod).arrayLen(mod),
24461619 else => unreachable,
24471620 };
24481621 if (a_len != b.sliceLen(mod)) {
24491622 return false;
24501623 }
24511624
2452 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2453 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);
2454 const a_ptr = switch (a_ty.ptrSize()) {
2455 .Slice => a.slicePtr(),
1625 const ptr_ty = ty.slicePtrFieldType(mod);
1626 const a_ptr = switch (a_ty.ptrSize(mod)) {
1627 .Slice => a.slicePtr(mod),
24561628 .One => a,
24571629 else => unreachable,
24581630 };
2459 return try eqlAdvanced(a_ptr, ptr_ty, b.slicePtr(), ptr_ty, mod, opt_sema);
1631 return try eqlAdvanced(a_ptr, ptr_ty, b.slicePtr(mod), ptr_ty, mod, opt_sema);
24601632 },
24611633 .Many, .C, .One => {},
24621634 },
24631635 .Struct => {
24641636 // A struct can be represented with one of:
2465 // .empty_struct_value,
24661637 // .the_one_possible_value,
24671638 // .aggregate,
24681639 // Note that we already checked above for matching tags, e.g. both .aggregate.
2469 return ty.onePossibleValue() != null;
1640 return (try ty.onePossibleValue(mod)) != null;
24701641 },
24711642 .Union => {
24721643 // Here we have to check for value equality, as-if `a` has been coerced to `ty`.
2473 if (ty.onePossibleValue() != null) {
1644 if ((try ty.onePossibleValue(mod)) != null) {
24741645 return true;
24751646 }
2476 if (a_ty.castTag(.anon_struct)) |payload| {
2477 const tuple = payload.data;
2478 if (tuple.values.len != 1) {
2479 return false;
2480 }
2481 const field_name = tuple.names[0];
2482 const union_obj = ty.cast(Type.Payload.Union).?.data;
2483 const field_index = union_obj.fields.getIndex(field_name) orelse return false;
2484 const tag_and_val = b.castTag(.@"union").?.data;
2485 var field_tag_buf: Value.Payload.U32 = .{
2486 .base = .{ .tag = .enum_field_index },
2487 .data = @intCast(u32, field_index),
2488 };
2489 const field_tag = Value.initPayload(&field_tag_buf.base);
2490 const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, mod);
2491 if (!tag_matches) return false;
2492 return eqlAdvanced(tag_and_val.val, union_obj.tag_ty, tuple.values[0], tuple.types[0], mod, opt_sema);
2493 }
24941647 return false;
24951648 },
24961649 .Float => {
24971650 switch (ty.floatBits(target)) {
2498 16 => return @bitCast(u16, a.toFloat(f16)) == @bitCast(u16, b.toFloat(f16)),
2499 32 => return @bitCast(u32, a.toFloat(f32)) == @bitCast(u32, b.toFloat(f32)),
2500 64 => return @bitCast(u64, a.toFloat(f64)) == @bitCast(u64, b.toFloat(f64)),
2501 80 => return @bitCast(u80, a.toFloat(f80)) == @bitCast(u80, b.toFloat(f80)),
2502 128 => return @bitCast(u128, a.toFloat(f128)) == @bitCast(u128, b.toFloat(f128)),
1651 16 => return @bitCast(u16, a.toFloat(f16, mod)) == @bitCast(u16, b.toFloat(f16, mod)),
1652 32 => return @bitCast(u32, a.toFloat(f32, mod)) == @bitCast(u32, b.toFloat(f32, mod)),
1653 64 => return @bitCast(u64, a.toFloat(f64, mod)) == @bitCast(u64, b.toFloat(f64, mod)),
1654 80 => return @bitCast(u80, a.toFloat(f80, mod)) == @bitCast(u80, b.toFloat(f80, mod)),
1655 128 => return @bitCast(u128, a.toFloat(f128, mod)) == @bitCast(u128, b.toFloat(f128, mod)),
25031656 else => unreachable,
25041657 }
25051658 },
25061659 .ComptimeFloat => {
2507 const a_float = a.toFloat(f128);
2508 const b_float = b.toFloat(f128);
1660 const a_float = a.toFloat(f128, mod);
1661 const b_float = b.toFloat(f128, mod);
25091662
25101663 const a_nan = std.math.isNan(a_float);
25111664 const b_nan = std.math.isNan(b_float);
......@@ -2514,570 +1667,215 @@ pub const Value = extern union {
25141667 if (a_nan) return true;
25151668 return a_float == b_float;
25161669 },
2517 .Optional => if (a_tag != .null_value and b_tag == .opt_payload) {
2518 var sub_pl: Payload.SubValue = .{
2519 .base = .{ .tag = b.tag() },
2520 .data = a,
2521 };
2522 const sub_val = Value.initPayload(&sub_pl.base);
2523 return eqlAdvanced(sub_val, ty, b, ty, mod, opt_sema);
2524 },
2525 .ErrorUnion => if (a_tag != .@"error" and b_tag == .eu_payload) {
2526 var sub_pl: Payload.SubValue = .{
2527 .base = .{ .tag = b.tag() },
2528 .data = a,
2529 };
2530 const sub_val = Value.initPayload(&sub_pl.base);
2531 return eqlAdvanced(sub_val, ty, b, ty, mod, opt_sema);
2532 },
1670 .Optional,
1671 .ErrorUnion,
1672 => unreachable, // handled by InternPool
25331673 else => {},
25341674 }
2535 if (a_tag == .null_value or a_tag == .@"error") return false;
2536 return (try orderAdvanced(a, b, target, opt_sema)).compare(.eq);
2537 }
2538
2539 /// This function is used by hash maps and so treats floating-point NaNs as equal
2540 /// to each other, and not equal to other floating-point values.
2541 pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
2542 const zig_ty_tag = ty.zigTypeTag();
2543 std.hash.autoHash(hasher, zig_ty_tag);
2544 if (val.isUndef()) return;
2545 // The value is runtime-known and shouldn't affect the hash.
2546 if (val.tag() == .runtime_value) return;
2547
2548 switch (zig_ty_tag) {
2549 .Opaque => unreachable, // Cannot hash opaque types
2550
2551 .Void,
2552 .NoReturn,
2553 .Undefined,
2554 .Null,
2555 => {},
2556
2557 .Type => {
2558 var buf: ToTypeBuffer = undefined;
2559 return val.toType(&buf).hashWithHasher(hasher, mod);
2560 },
2561 .Float => {
2562 // For hash/eql purposes, we treat floats as their IEEE integer representation.
2563 switch (ty.floatBits(mod.getTarget())) {
2564 16 => std.hash.autoHash(hasher, @bitCast(u16, val.toFloat(f16))),
2565 32 => std.hash.autoHash(hasher, @bitCast(u32, val.toFloat(f32))),
2566 64 => std.hash.autoHash(hasher, @bitCast(u64, val.toFloat(f64))),
2567 80 => std.hash.autoHash(hasher, @bitCast(u80, val.toFloat(f80))),
2568 128 => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128))),
2569 else => unreachable,
2570 }
2571 },
2572 .ComptimeFloat => {
2573 const float = val.toFloat(f128);
2574 const is_nan = std.math.isNan(float);
2575 std.hash.autoHash(hasher, is_nan);
2576 if (!is_nan) {
2577 std.hash.autoHash(hasher, @bitCast(u128, float));
2578 } else {
2579 std.hash.autoHash(hasher, std.math.signbit(float));
2580 }
2581 },
2582 .Bool, .Int, .ComptimeInt, .Pointer => switch (val.tag()) {
2583 .slice => {
2584 const slice = val.castTag(.slice).?.data;
2585 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2586 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);
2587 hash(slice.ptr, ptr_ty, hasher, mod);
2588 hash(slice.len, Type.usize, hasher, mod);
2589 },
2590
2591 else => return hashPtr(val, hasher, mod.getTarget()),
2592 },
2593 .Array, .Vector => {
2594 const len = ty.arrayLen();
2595 const elem_ty = ty.childType();
2596 var index: usize = 0;
2597 var elem_value_buf: ElemValueBuffer = undefined;
2598 while (index < len) : (index += 1) {
2599 const elem_val = val.elemValueBuffer(mod, index, &elem_value_buf);
2600 elem_val.hash(elem_ty, hasher, mod);
2601 }
2602 },
2603 .Struct => {
2604 switch (val.tag()) {
2605 .empty_struct_value => {},
2606 .aggregate => {
2607 const field_values = val.castTag(.aggregate).?.data;
2608 for (field_values, 0..) |field_val, i| {
2609 const field_ty = ty.structFieldType(i);
2610 field_val.hash(field_ty, hasher, mod);
2611 }
2612 },
2613 else => unreachable,
2614 }
2615 },
2616 .Optional => {
2617 if (val.castTag(.opt_payload)) |payload| {
2618 std.hash.autoHash(hasher, true); // non-null
2619 const sub_val = payload.data;
2620 var buffer: Type.Payload.ElemType = undefined;
2621 const sub_ty = ty.optionalChild(&buffer);
2622 sub_val.hash(sub_ty, hasher, mod);
2623 } else {
2624 std.hash.autoHash(hasher, false); // null
2625 }
2626 },
2627 .ErrorUnion => {
2628 if (val.tag() == .@"error") {
2629 std.hash.autoHash(hasher, false); // error
2630 const sub_ty = ty.errorUnionSet();
2631 val.hash(sub_ty, hasher, mod);
2632 return;
2633 }
2634
2635 if (val.castTag(.eu_payload)) |payload| {
2636 std.hash.autoHash(hasher, true); // payload
2637 const sub_ty = ty.errorUnionPayload();
2638 payload.data.hash(sub_ty, hasher, mod);
2639 return;
2640 } else unreachable;
2641 },
2642 .ErrorSet => {
2643 // just hash the literal error value. this is the most stable
2644 // thing between compiler invocations. we can't use the error
2645 // int cause (1) its not stable and (2) we don't have access to mod.
2646 hasher.update(val.getError().?);
2647 },
2648 .Enum => {
2649 var enum_space: Payload.U64 = undefined;
2650 const int_val = val.enumToInt(ty, &enum_space);
2651 hashInt(int_val, hasher, mod.getTarget());
2652 },
2653 .Union => {
2654 const union_obj = val.cast(Payload.Union).?.data;
2655 if (ty.unionTagType()) |tag_ty| {
2656 union_obj.tag.hash(tag_ty, hasher, mod);
2657 }
2658 const active_field_ty = ty.unionFieldType(union_obj.tag, mod);
2659 union_obj.val.hash(active_field_ty, hasher, mod);
2660 },
2661 .Fn => {
2662 // Note that this hashes the *Fn/*ExternFn rather than the *Decl.
2663 // This is to differentiate function bodies from function pointers.
2664 // This is currently redundant since we already hash the zig type tag
2665 // at the top of this function.
2666 if (val.castTag(.function)) |func| {
2667 std.hash.autoHash(hasher, func.data);
2668 } else if (val.castTag(.extern_fn)) |func| {
2669 std.hash.autoHash(hasher, func.data);
2670 } else unreachable;
2671 },
2672 .Frame => {
2673 @panic("TODO implement hashing frame values");
2674 },
2675 .AnyFrame => {
2676 @panic("TODO implement hashing anyframe values");
2677 },
2678 .EnumLiteral => {
2679 const bytes = val.castTag(.enum_literal).?.data;
2680 hasher.update(bytes);
2681 },
2682 }
1675 return (try orderAdvanced(a, b, mod, opt_sema)).compare(.eq);
26831676 }
26841677
2685 /// This is a more conservative hash function that produces equal hashes for values
2686 /// that can coerce into each other.
2687 /// This function is used by hash maps and so treats floating-point NaNs as equal
2688 /// to each other, and not equal to other floating-point values.
2689 pub fn hashUncoerced(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void {
2690 if (val.isUndef()) return;
2691 // The value is runtime-known and shouldn't affect the hash.
2692 if (val.tag() == .runtime_value) return;
2693
2694 switch (ty.zigTypeTag()) {
2695 .Opaque => unreachable, // Cannot hash opaque types
2696 .Void,
2697 .NoReturn,
2698 .Undefined,
2699 .Null,
2700 .Struct, // It sure would be nice to do something clever with structs.
2701 => |zig_type_tag| std.hash.autoHash(hasher, zig_type_tag),
2702 .Type => {
2703 var buf: ToTypeBuffer = undefined;
2704 val.toType(&buf).hashWithHasher(hasher, mod);
2705 },
2706 .Float, .ComptimeFloat => std.hash.autoHash(hasher, @bitCast(u128, val.toFloat(f128))),
2707 .Bool, .Int, .ComptimeInt, .Pointer, .Fn => switch (val.tag()) {
2708 .slice => {
2709 const slice = val.castTag(.slice).?.data;
2710 var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined;
2711 const ptr_ty = ty.slicePtrFieldType(&ptr_buf);
2712 slice.ptr.hashUncoerced(ptr_ty, hasher, mod);
2713 },
2714 else => val.hashPtr(hasher, mod.getTarget()),
2715 },
2716 .Array, .Vector => {
2717 const len = ty.arrayLen();
2718 const elem_ty = ty.childType();
2719 var index: usize = 0;
2720 var elem_value_buf: ElemValueBuffer = undefined;
2721 while (index < len) : (index += 1) {
2722 const elem_val = val.elemValueBuffer(mod, index, &elem_value_buf);
2723 elem_val.hashUncoerced(elem_ty, hasher, mod);
2724 }
2725 },
2726 .Optional => if (val.castTag(.opt_payload)) |payload| {
2727 var buf: Type.Payload.ElemType = undefined;
2728 const child_ty = ty.optionalChild(&buf);
2729 payload.data.hashUncoerced(child_ty, hasher, mod);
2730 } else std.hash.autoHash(hasher, std.builtin.TypeId.Null),
2731 .ErrorSet, .ErrorUnion => if (val.getError()) |err| hasher.update(err) else {
2732 const pl_ty = ty.errorUnionPayload();
2733 val.castTag(.eu_payload).?.data.hashUncoerced(pl_ty, hasher, mod);
1678 pub fn isComptimeMutablePtr(val: Value, mod: *Module) bool {
1679 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1680 .ptr => |ptr| switch (ptr.addr) {
1681 .mut_decl, .comptime_field => true,
1682 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isComptimeMutablePtr(mod),
1683 .elem, .field => |base_index| base_index.base.toValue().isComptimeMutablePtr(mod),
1684 else => false,
27341685 },
2735 .Enum, .EnumLiteral, .Union => {
2736 hasher.update(val.tagName(ty, mod));
2737 if (val.cast(Payload.Union)) |union_obj| {
2738 const active_field_ty = ty.unionFieldType(union_obj.data.tag, mod);
2739 union_obj.data.val.hashUncoerced(active_field_ty, hasher, mod);
2740 } else std.hash.autoHash(hasher, std.builtin.TypeId.Void);
2741 },
2742 .Frame => @panic("TODO implement hashing frame values"),
2743 .AnyFrame => @panic("TODO implement hashing anyframe values"),
2744 }
2745 }
2746
2747 pub const ArrayHashContext = struct {
2748 ty: Type,
2749 mod: *Module,
2750
2751 pub fn hash(self: @This(), val: Value) u32 {
2752 const other_context: HashContext = .{ .ty = self.ty, .mod = self.mod };
2753 return @truncate(u32, other_context.hash(val));
2754 }
2755 pub fn eql(self: @This(), a: Value, b: Value, b_index: usize) bool {
2756 _ = b_index;
2757 return a.eql(b, self.ty, self.mod);
2758 }
2759 };
2760
2761 pub const HashContext = struct {
2762 ty: Type,
2763 mod: *Module,
2764
2765 pub fn hash(self: @This(), val: Value) u64 {
2766 var hasher = std.hash.Wyhash.init(0);
2767 val.hash(self.ty, &hasher, self.mod);
2768 return hasher.final();
2769 }
2770
2771 pub fn eql(self: @This(), a: Value, b: Value) bool {
2772 return a.eql(b, self.ty, self.mod);
2773 }
2774 };
2775
2776 pub fn isComptimeMutablePtr(val: Value) bool {
2777 return switch (val.tag()) {
2778 .decl_ref_mut, .comptime_field_ptr => true,
2779 .elem_ptr => isComptimeMutablePtr(val.castTag(.elem_ptr).?.data.array_ptr),
2780 .field_ptr => isComptimeMutablePtr(val.castTag(.field_ptr).?.data.container_ptr),
2781 .eu_payload_ptr => isComptimeMutablePtr(val.castTag(.eu_payload_ptr).?.data.container_ptr),
2782 .opt_payload_ptr => isComptimeMutablePtr(val.castTag(.opt_payload_ptr).?.data.container_ptr),
2783 .slice => isComptimeMutablePtr(val.castTag(.slice).?.data.ptr),
2784
27851686 else => false,
27861687 };
27871688 }
27881689
2789 pub fn canMutateComptimeVarState(val: Value) bool {
2790 if (val.isComptimeMutablePtr()) return true;
2791 switch (val.tag()) {
2792 .repeated => return val.castTag(.repeated).?.data.canMutateComptimeVarState(),
2793 .eu_payload => return val.castTag(.eu_payload).?.data.canMutateComptimeVarState(),
2794 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
2795 .opt_payload => return val.castTag(.opt_payload).?.data.canMutateComptimeVarState(),
2796 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.canMutateComptimeVarState(),
2797 .aggregate => {
2798 const fields = val.castTag(.aggregate).?.data;
2799 for (fields) |field| {
2800 if (field.canMutateComptimeVarState()) return true;
2801 }
2802 return false;
1690 pub fn canMutateComptimeVarState(val: Value, mod: *Module) bool {
1691 return val.isComptimeMutablePtr(mod) or switch (val.toIntern()) {
1692 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1693 .error_union => |error_union| switch (error_union.val) {
1694 .err_name => false,
1695 .payload => |payload| payload.toValue().canMutateComptimeVarState(mod),
1696 },
1697 .ptr => |ptr| switch (ptr.addr) {
1698 .eu_payload, .opt_payload => |base| base.toValue().canMutateComptimeVarState(mod),
1699 else => false,
1700 },
1701 .opt => |opt| switch (opt.val) {
1702 .none => false,
1703 else => |payload| payload.toValue().canMutateComptimeVarState(mod),
1704 },
1705 .aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
1706 if (elem.toValue().canMutateComptimeVarState(mod)) break true;
1707 } else false,
1708 .un => |un| un.val.toValue().canMutateComptimeVarState(mod),
1709 else => false,
28031710 },
2804 .@"union" => return val.cast(Payload.Union).?.data.val.canMutateComptimeVarState(),
2805 .slice => return val.castTag(.slice).?.data.ptr.canMutateComptimeVarState(),
2806 else => return false,
2807 }
1711 };
28081712 }
28091713
28101714 /// Gets the decl referenced by this pointer. If the pointer does not point
28111715 /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),
28121716 /// this function returns null.
2813 pub fn pointerDecl(val: Value) ?Module.Decl.Index {
2814 return switch (val.tag()) {
2815 .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index,
2816 .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
2817 .function => val.castTag(.function).?.data.owner_decl,
2818 .variable => val.castTag(.variable).?.data.owner_decl,
2819 .decl_ref => val.cast(Payload.Decl).?.data,
1717 pub fn pointerDecl(val: Value, mod: *Module) ?Module.Decl.Index {
1718 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1719 .variable => |variable| variable.decl,
1720 .extern_func => |extern_func| extern_func.decl,
1721 .func => |func| mod.funcPtr(func.index).owner_decl,
1722 .ptr => |ptr| switch (ptr.addr) {
1723 .decl => |decl| decl,
1724 .mut_decl => |mut_decl| mut_decl.decl,
1725 else => null,
1726 },
28201727 else => null,
28211728 };
28221729 }
28231730
2824 fn hashInt(int_val: Value, hasher: *std.hash.Wyhash, target: Target) void {
1731 fn hashInt(int_val: Value, hasher: *std.hash.Wyhash, mod: *Module) void {
28251732 var buffer: BigIntSpace = undefined;
2826 const big = int_val.toBigInt(&buffer, target);
1733 const big = int_val.toBigInt(&buffer, mod);
28271734 std.hash.autoHash(hasher, big.positive);
28281735 for (big.limbs) |limb| {
28291736 std.hash.autoHash(hasher, limb);
28301737 }
28311738 }
28321739
2833 fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, target: Target) void {
2834 switch (ptr_val.tag()) {
2835 .decl_ref,
2836 .decl_ref_mut,
2837 .extern_fn,
2838 .function,
2839 .variable,
2840 => {
2841 const decl: Module.Decl.Index = ptr_val.pointerDecl().?;
2842 std.hash.autoHash(hasher, decl);
2843 },
2844 .comptime_field_ptr => {
2845 std.hash.autoHash(hasher, Value.Tag.comptime_field_ptr);
2846 },
2847
2848 .elem_ptr => {
2849 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
2850 hashPtr(elem_ptr.array_ptr, hasher, target);
2851 std.hash.autoHash(hasher, Value.Tag.elem_ptr);
2852 std.hash.autoHash(hasher, elem_ptr.index);
2853 },
2854 .field_ptr => {
2855 const field_ptr = ptr_val.castTag(.field_ptr).?.data;
2856 std.hash.autoHash(hasher, Value.Tag.field_ptr);
2857 hashPtr(field_ptr.container_ptr, hasher, target);
2858 std.hash.autoHash(hasher, field_ptr.field_index);
2859 },
2860 .eu_payload_ptr => {
2861 const err_union_ptr = ptr_val.castTag(.eu_payload_ptr).?.data;
2862 std.hash.autoHash(hasher, Value.Tag.eu_payload_ptr);
2863 hashPtr(err_union_ptr.container_ptr, hasher, target);
2864 },
2865 .opt_payload_ptr => {
2866 const opt_ptr = ptr_val.castTag(.opt_payload_ptr).?.data;
2867 std.hash.autoHash(hasher, Value.Tag.opt_payload_ptr);
2868 hashPtr(opt_ptr.container_ptr, hasher, target);
2869 },
2870
2871 .zero,
2872 .one,
2873 .null_value,
2874 .int_u64,
2875 .int_i64,
2876 .int_big_positive,
2877 .int_big_negative,
2878 .bool_false,
2879 .bool_true,
2880 .the_only_possible_value,
2881 .lazy_align,
2882 .lazy_size,
2883 => return hashInt(ptr_val, hasher, target),
1740 pub const slice_ptr_index = 0;
1741 pub const slice_len_index = 1;
28841742
2885 else => unreachable,
2886 }
2887 }
2888
2889 pub fn slicePtr(val: Value) Value {
2890 return switch (val.tag()) {
2891 .slice => val.castTag(.slice).?.data.ptr,
2892 // TODO this should require being a slice tag, and not allow decl_ref, field_ptr, etc.
2893 .decl_ref, .decl_ref_mut, .field_ptr, .elem_ptr, .comptime_field_ptr => val,
2894 else => unreachable,
2895 };
1743 pub fn slicePtr(val: Value, mod: *Module) Value {
1744 return mod.intern_pool.slicePtr(val.toIntern()).toValue();
28961745 }
28971746
28981747 pub fn sliceLen(val: Value, mod: *Module) u64 {
2899 return switch (val.tag()) {
2900 .slice => val.castTag(.slice).?.data.len.toUnsignedInt(mod.getTarget()),
2901 .decl_ref => {
2902 const decl_index = val.castTag(.decl_ref).?.data;
2903 const decl = mod.declPtr(decl_index);
2904 if (decl.ty.zigTypeTag() == .Array) {
2905 return decl.ty.arrayLen();
2906 } else {
2907 return 1;
2908 }
2909 },
2910 .decl_ref_mut => {
2911 const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index;
2912 const decl = mod.declPtr(decl_index);
2913 if (decl.ty.zigTypeTag() == .Array) {
2914 return decl.ty.arrayLen();
2915 } else {
2916 return 1;
2917 }
2918 },
2919 .comptime_field_ptr => {
2920 const payload = val.castTag(.comptime_field_ptr).?.data;
2921 if (payload.field_ty.zigTypeTag() == .Array) {
2922 return payload.field_ty.arrayLen();
2923 } else {
2924 return 1;
2925 }
1748 const ptr = mod.intern_pool.indexToKey(val.toIntern()).ptr;
1749 return switch (ptr.len) {
1750 .none => switch (mod.intern_pool.indexToKey(switch (ptr.addr) {
1751 .decl => |decl| mod.declPtr(decl).ty.toIntern(),
1752 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(),
1753 .comptime_field => |comptime_field| mod.intern_pool.typeOf(comptime_field),
1754 else => unreachable,
1755 })) {
1756 .array_type => |array_type| array_type.len,
1757 else => 1,
29261758 },
2927 else => unreachable,
1759 else => ptr.len.toValue().toUnsignedInt(mod),
29281760 };
29291761 }
29301762
29311763 /// Asserts the value is a single-item pointer to an array, or an array,
29321764 /// or an unknown-length pointer, and returns the element value at the index.
2933 pub fn elemValue(val: Value, mod: *Module, arena: Allocator, index: usize) !Value {
2934 return elemValueAdvanced(val, mod, index, arena, undefined);
2935 }
2936
2937 pub const ElemValueBuffer = Payload.U64;
2938
2939 pub fn elemValueBuffer(val: Value, mod: *Module, index: usize, buffer: *ElemValueBuffer) Value {
2940 return elemValueAdvanced(val, mod, index, null, buffer) catch unreachable;
2941 }
2942
2943 pub fn elemValueAdvanced(
2944 val: Value,
2945 mod: *Module,
2946 index: usize,
2947 arena: ?Allocator,
2948 buffer: *ElemValueBuffer,
2949 ) error{OutOfMemory}!Value {
2950 switch (val.tag()) {
2951 // This is the case of accessing an element of an undef array.
2952 .undef => return Value.undef,
2953 .empty_array => unreachable, // out of bounds array index
2954 .empty_struct_value => unreachable, // out of bounds array index
2955
2956 .empty_array_sentinel => {
2957 assert(index == 0); // The only valid index for an empty array with sentinel.
2958 return val.castTag(.empty_array_sentinel).?.data;
2959 },
2960
2961 .bytes => {
2962 const byte = val.castTag(.bytes).?.data[index];
2963 if (arena) |a| {
2964 return Tag.int_u64.create(a, byte);
2965 } else {
2966 buffer.* = .{
2967 .base = .{ .tag = .int_u64 },
2968 .data = byte,
2969 };
2970 return initPayload(&buffer.base);
2971 }
2972 },
2973 .str_lit => {
2974 const str_lit = val.castTag(.str_lit).?.data;
2975 const bytes = mod.string_literal_bytes.items[str_lit.index..][0..str_lit.len];
2976 const byte = bytes[index];
2977 if (arena) |a| {
2978 return Tag.int_u64.create(a, byte);
2979 } else {
2980 buffer.* = .{
2981 .base = .{ .tag = .int_u64 },
2982 .data = byte,
2983 };
2984 return initPayload(&buffer.base);
2985 }
2986 },
2987
2988 // No matter the index; all the elements are the same!
2989 .repeated => return val.castTag(.repeated).?.data,
2990
2991 .aggregate => return val.castTag(.aggregate).?.data[index],
2992 .slice => return val.castTag(.slice).?.data.ptr.elemValueAdvanced(mod, index, arena, buffer),
2993
2994 .decl_ref => return mod.declPtr(val.castTag(.decl_ref).?.data).val.elemValueAdvanced(mod, index, arena, buffer),
2995 .decl_ref_mut => return mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.elemValueAdvanced(mod, index, arena, buffer),
2996 .comptime_field_ptr => return val.castTag(.comptime_field_ptr).?.data.field_val.elemValueAdvanced(mod, index, arena, buffer),
2997 .elem_ptr => {
2998 const data = val.castTag(.elem_ptr).?.data;
2999 return data.array_ptr.elemValueAdvanced(mod, index + data.index, arena, buffer);
1765 pub fn elemValue(val: Value, mod: *Module, index: usize) Allocator.Error!Value {
1766 return switch (val.ip_index) {
1767 .none => switch (val.tag()) {
1768 .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]),
1769 .repeated => val.castTag(.repeated).?.data,
1770 .aggregate => val.castTag(.aggregate).?.data[index],
1771 .slice => val.castTag(.slice).?.data.ptr.elemValue(mod, index),
1772 else => unreachable,
30001773 },
3001 .field_ptr => {
3002 const data = val.castTag(.field_ptr).?.data;
3003 if (data.container_ptr.pointerDecl()) |decl_index| {
3004 const container_decl = mod.declPtr(decl_index);
3005 const field_type = data.container_ty.structFieldType(data.field_index);
3006 const field_val = container_decl.val.fieldValue(field_type, data.field_index);
3007 return field_val.elemValueAdvanced(mod, index, arena, buffer);
3008 } else unreachable;
1774 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1775 .undef => |ty| (try mod.intern(.{
1776 .undef = ty.toType().elemType2(mod).toIntern(),
1777 })).toValue(),
1778 .ptr => |ptr| switch (ptr.addr) {
1779 .decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
1780 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
1781 .toValue().elemValue(mod, index),
1782 .int, .eu_payload => unreachable,
1783 .opt_payload => |base| base.toValue().elemValue(mod, index),
1784 .comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
1785 .elem => |elem| elem.base.toValue().elemValue(mod, index + @intCast(usize, elem.index)),
1786 .field => |field| if (field.base.toValue().pointerDecl(mod)) |decl_index| {
1787 const base_decl = mod.declPtr(decl_index);
1788 const field_val = try base_decl.val.fieldValue(mod, @intCast(usize, field.index));
1789 return field_val.elemValue(mod, index);
1790 } else unreachable,
1791 },
1792 .opt => |opt| opt.val.toValue().elemValue(mod, index),
1793 .aggregate => |aggregate| {
1794 const len = mod.intern_pool.aggregateTypeLen(aggregate.ty);
1795 if (index < len) return switch (aggregate.storage) {
1796 .bytes => |bytes| try mod.intern(.{ .int = .{
1797 .ty = .u8_type,
1798 .storage = .{ .u64 = bytes[index] },
1799 } }),
1800 .elems => |elems| elems[index],
1801 .repeated_elem => |elem| elem,
1802 }.toValue();
1803 assert(index == len);
1804 return mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel.toValue();
1805 },
1806 else => unreachable,
30091807 },
1808 };
1809 }
30101810
3011 // The child type of arrays which have only one possible value need
3012 // to have only one possible value itself.
3013 .the_only_possible_value => return val,
3014
3015 .opt_payload_ptr => return val.castTag(.opt_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
3016 .eu_payload_ptr => return val.castTag(.eu_payload_ptr).?.data.container_ptr.elemValueAdvanced(mod, index, arena, buffer),
3017
3018 .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
3019 .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer),
1811 pub fn isLazyAlign(val: Value, mod: *Module) bool {
1812 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1813 .int => |int| int.storage == .lazy_align,
1814 else => false,
1815 };
1816 }
30201817
3021 // These values will implicitly be treated as `repeated`.
3022 .zero,
3023 .one,
3024 .bool_false,
3025 .bool_true,
3026 .int_i64,
3027 .int_u64,
3028 => return val,
1818 pub fn isLazySize(val: Value, mod: *Module) bool {
1819 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1820 .int => |int| int.storage == .lazy_size,
1821 else => false,
1822 };
1823 }
30291824
3030 else => unreachable,
3031 }
1825 pub fn isRuntimeValue(val: Value, mod: *Module) bool {
1826 return mod.intern_pool.indexToKey(val.toIntern()) == .runtime_value;
30321827 }
30331828
30341829 /// Returns true if a Value is backed by a variable
3035 pub fn isVariable(
3036 val: Value,
3037 mod: *Module,
3038 ) bool {
3039 return switch (val.tag()) {
3040 .slice => val.castTag(.slice).?.data.ptr.isVariable(mod),
3041 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isVariable(mod),
3042 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isVariable(mod),
3043 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isVariable(mod),
3044 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isVariable(mod),
3045 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isVariable(mod),
3046 .decl_ref => {
3047 const decl = mod.declPtr(val.castTag(.decl_ref).?.data);
3048 assert(decl.has_tv);
3049 return decl.val.isVariable(mod);
3050 },
3051 .decl_ref_mut => {
3052 const decl = mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index);
3053 assert(decl.has_tv);
3054 return decl.val.isVariable(mod);
3055 },
3056
1830 pub fn isVariable(val: Value, mod: *Module) bool {
1831 return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) {
30571832 .variable => true,
1833 .ptr => |ptr| switch (ptr.addr) {
1834 .decl => |decl_index| {
1835 const decl = mod.declPtr(decl_index);
1836 assert(decl.has_tv);
1837 return decl.val.isVariable(mod);
1838 },
1839 .mut_decl => |mut_decl| {
1840 const decl = mod.declPtr(mut_decl.decl);
1841 assert(decl.has_tv);
1842 return decl.val.isVariable(mod);
1843 },
1844 .int => false,
1845 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isVariable(mod),
1846 .comptime_field => |comptime_field| comptime_field.toValue().isVariable(mod),
1847 .elem, .field => |base_index| base_index.base.toValue().isVariable(mod),
1848 },
30581849 else => false,
30591850 };
30601851 }
30611852
30621853 pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {
3063 return switch (val.tag()) {
1854 return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) {
30641855 .variable => false,
30651856 else => val.isPtrToThreadLocalInner(mod),
30661857 };
30671858 }
30681859
3069 fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {
3070 return switch (val.tag()) {
3071 .slice => val.castTag(.slice).?.data.ptr.isPtrToThreadLocalInner(mod),
3072 .comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isPtrToThreadLocalInner(mod),
3073 .elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isPtrToThreadLocalInner(mod),
3074 .field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
3075 .eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
3076 .opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
3077 .decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isPtrToThreadLocalInner(mod),
3078 .decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isPtrToThreadLocalInner(mod),
3079
3080 .variable => val.castTag(.variable).?.data.is_threadlocal,
1860 pub fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {
1861 return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) {
1862 .variable => |variable| variable.is_threadlocal,
1863 .ptr => |ptr| switch (ptr.addr) {
1864 .decl => |decl_index| {
1865 const decl = mod.declPtr(decl_index);
1866 assert(decl.has_tv);
1867 return decl.val.isPtrToThreadLocalInner(mod);
1868 },
1869 .mut_decl => |mut_decl| {
1870 const decl = mod.declPtr(mut_decl.decl);
1871 assert(decl.has_tv);
1872 return decl.val.isPtrToThreadLocalInner(mod);
1873 },
1874 .int => false,
1875 .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isPtrToThreadLocalInner(mod),
1876 .comptime_field => |comptime_field| comptime_field.toValue().isPtrToThreadLocalInner(mod),
1877 .elem, .field => |base_index| base_index.base.toValue().isPtrToThreadLocalInner(mod),
1878 },
30811879 else => false,
30821880 };
30831881 }
......@@ -3090,238 +1888,239 @@ pub const Value = extern union {
30901888 start: usize,
30911889 end: usize,
30921890 ) error{OutOfMemory}!Value {
3093 return switch (val.tag()) {
3094 .empty_array_sentinel => if (start == 0 and end == 1) val else Value.initTag(.empty_array),
3095 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
3096 .str_lit => {
3097 const str_lit = val.castTag(.str_lit).?.data;
3098 return Tag.str_lit.create(arena, .{
3099 .index = @intCast(u32, str_lit.index + start),
3100 .len = @intCast(u32, end - start),
3101 });
1891 // TODO: write something like getCoercedInts to avoid needing to dupe
1892 return switch (val.ip_index) {
1893 .none => switch (val.tag()) {
1894 .slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
1895 .bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
1896 .repeated => val,
1897 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
1898 else => unreachable,
31021899 },
3103 .aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
3104 .slice => sliceArray(val.castTag(.slice).?.data.ptr, mod, arena, start, end),
3105
3106 .decl_ref => sliceArray(mod.declPtr(val.castTag(.decl_ref).?.data).val, mod, arena, start, end),
3107 .decl_ref_mut => sliceArray(mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val, mod, arena, start, end),
3108 .comptime_field_ptr => sliceArray(val.castTag(.comptime_field_ptr).?.data.field_val, mod, arena, start, end),
3109 .elem_ptr => blk: {
3110 const elem_ptr = val.castTag(.elem_ptr).?.data;
3111 break :blk sliceArray(elem_ptr.array_ptr, mod, arena, start + elem_ptr.index, end + elem_ptr.index);
1900 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1901 .ptr => |ptr| switch (ptr.addr) {
1902 .decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
1903 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
1904 .sliceArray(mod, arena, start, end),
1905 .comptime_field => |comptime_field| comptime_field.toValue()
1906 .sliceArray(mod, arena, start, end),
1907 .elem => |elem| elem.base.toValue()
1908 .sliceArray(mod, arena, start + @intCast(usize, elem.index), end + @intCast(usize, elem.index)),
1909 else => unreachable,
1910 },
1911 .aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{
1912 .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) {
1913 .array_type => |array_type| try mod.arrayType(.{
1914 .len = @intCast(u32, end - start),
1915 .child = array_type.child,
1916 .sentinel = if (end == array_type.len) array_type.sentinel else .none,
1917 }),
1918 .vector_type => |vector_type| try mod.vectorType(.{
1919 .len = @intCast(u32, end - start),
1920 .child = vector_type.child,
1921 }),
1922 else => unreachable,
1923 }.toIntern(),
1924 .storage = switch (aggregate.storage) {
1925 .bytes => .{ .bytes = try arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) },
1926 .elems => .{ .elems = try arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) },
1927 .repeated_elem => |elem| .{ .repeated_elem = elem },
1928 },
1929 } })).toValue(),
1930 else => unreachable,
31121931 },
3113
3114 .repeated,
3115 .the_only_possible_value,
3116 => val,
3117
3118 else => unreachable,
31191932 };
31201933 }
31211934
3122 pub fn fieldValue(val: Value, ty: Type, index: usize) Value {
3123 switch (val.tag()) {
3124 .aggregate => {
3125 const field_values = val.castTag(.aggregate).?.data;
3126 return field_values[index];
1935 pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
1936 return switch (val.ip_index) {
1937 .none => switch (val.tag()) {
1938 .aggregate => {
1939 const field_values = val.castTag(.aggregate).?.data;
1940 return field_values[index];
1941 },
1942 .@"union" => {
1943 const payload = val.castTag(.@"union").?.data;
1944 // TODO assert the tag is correct
1945 return payload.val;
1946 },
1947 else => unreachable,
31271948 },
3128 .@"union" => {
3129 const payload = val.castTag(.@"union").?.data;
1949 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
1950 .undef => |ty| (try mod.intern(.{
1951 .undef = ty.toType().structFieldType(index, mod).toIntern(),
1952 })).toValue(),
1953 .aggregate => |aggregate| switch (aggregate.storage) {
1954 .bytes => |bytes| try mod.intern(.{ .int = .{
1955 .ty = .u8_type,
1956 .storage = .{ .u64 = bytes[index] },
1957 } }),
1958 .elems => |elems| elems[index],
1959 .repeated_elem => |elem| elem,
1960 }.toValue(),
31301961 // TODO assert the tag is correct
3131 return payload.val;
3132 },
3133
3134 .the_only_possible_value => return ty.onePossibleValue().?,
3135
3136 .empty_struct_value => {
3137 if (ty.isSimpleTupleOrAnonStruct()) {
3138 const tuple = ty.tupleFields();
3139 return tuple.values[index];
3140 }
3141 if (ty.structFieldValueComptime(index)) |some| {
3142 return some;
3143 }
3144 unreachable;
1962 .un => |un| un.val.toValue(),
1963 else => unreachable,
31451964 },
3146 .undef => return Value.undef,
3147
3148 else => unreachable,
3149 }
1965 };
31501966 }
31511967
3152 pub fn unionTag(val: Value) Value {
3153 switch (val.tag()) {
3154 .undef, .enum_field_index => return val,
3155 .@"union" => return val.castTag(.@"union").?.data.tag,
1968 pub fn unionTag(val: Value, mod: *Module) Value {
1969 if (val.ip_index == .none) return val.castTag(.@"union").?.data.tag;
1970 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
1971 .undef, .enum_tag => val,
1972 .un => |un| un.tag.toValue(),
31561973 else => unreachable,
3157 }
1974 };
31581975 }
31591976
31601977 /// Returns a pointer to the element value at the index.
31611978 pub fn elemPtr(
31621979 val: Value,
3163 ty: Type,
3164 arena: Allocator,
1980 elem_ptr_ty: Type,
31651981 index: usize,
31661982 mod: *Module,
31671983 ) Allocator.Error!Value {
3168 const elem_ty = ty.elemType2();
3169 const ptr_val = switch (val.tag()) {
3170 .slice => val.castTag(.slice).?.data.ptr,
1984 const elem_ty = elem_ptr_ty.childType(mod);
1985 const ptr_val = switch (mod.intern_pool.indexToKey(val.toIntern())) {
1986 .ptr => |ptr| ptr: {
1987 switch (ptr.addr) {
1988 .elem => |elem| if (mod.intern_pool.typeOf(elem.base).toType().elemType2(mod).eql(elem_ty, mod))
1989 return (try mod.intern(.{ .ptr = .{
1990 .ty = elem_ptr_ty.toIntern(),
1991 .addr = .{ .elem = .{
1992 .base = elem.base,
1993 .index = elem.index + index,
1994 } },
1995 } })).toValue(),
1996 else => {},
1997 }
1998 break :ptr switch (ptr.len) {
1999 .none => val,
2000 else => val.slicePtr(mod),
2001 };
2002 },
31712003 else => val,
31722004 };
3173
3174 if (ptr_val.tag() == .elem_ptr) {
3175 const elem_ptr = ptr_val.castTag(.elem_ptr).?.data;
3176 if (elem_ptr.elem_ty.eql(elem_ty, mod)) {
3177 return Tag.elem_ptr.create(arena, .{
3178 .array_ptr = elem_ptr.array_ptr,
3179 .elem_ty = elem_ptr.elem_ty,
3180 .index = elem_ptr.index + index,
3181 });
3182 }
3183 }
3184 return Tag.elem_ptr.create(arena, .{
3185 .array_ptr = ptr_val,
3186 .elem_ty = elem_ty,
3187 .index = index,
3188 });
3189 }
3190
3191 pub fn isUndef(self: Value) bool {
3192 return self.tag() == .undef;
2005 var ptr_ty_key = mod.intern_pool.indexToKey(elem_ptr_ty.toIntern()).ptr_type;
2006 assert(ptr_ty_key.flags.size != .Slice);
2007 ptr_ty_key.flags.size = .Many;
2008 return (try mod.intern(.{ .ptr = .{
2009 .ty = elem_ptr_ty.toIntern(),
2010 .addr = .{ .elem = .{
2011 .base = (try mod.getCoerced(ptr_val, try mod.ptrType(ptr_ty_key))).toIntern(),
2012 .index = index,
2013 } },
2014 } })).toValue();
2015 }
2016
2017 pub fn isUndef(val: Value, mod: *Module) bool {
2018 if (val.ip_index == .none) return false;
2019 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2020 .undef => true,
2021 .simple_value => |v| v == .undefined,
2022 else => false,
2023 };
31932024 }
31942025
31952026 /// TODO: check for cases such as array that is not marked undef but all the element
31962027 /// values are marked undef, or struct that is not marked undef but all fields are marked
31972028 /// undef, etc.
3198 pub fn isUndefDeep(self: Value) bool {
3199 return self.isUndef();
2029 pub fn isUndefDeep(val: Value, mod: *Module) bool {
2030 return val.isUndef(mod);
32002031 }
32012032
32022033 /// Returns true if any value contained in `self` is undefined.
3203 /// TODO: check for cases such as array that is not marked undef but all the element
3204 /// values are marked undef, or struct that is not marked undef but all fields are marked
3205 /// undef, etc.
3206 pub fn anyUndef(self: Value, mod: *Module) bool {
3207 switch (self.tag()) {
3208 .slice => {
3209 const payload = self.castTag(.slice).?;
3210 const len = payload.data.len.toUnsignedInt(mod.getTarget());
3211
3212 var elem_value_buf: ElemValueBuffer = undefined;
3213 var i: usize = 0;
3214 while (i < len) : (i += 1) {
3215 const elem_val = payload.data.ptr.elemValueBuffer(mod, i, &elem_value_buf);
3216 if (elem_val.anyUndef(mod)) return true;
3217 }
3218 },
3219
3220 .aggregate => {
3221 const payload = self.castTag(.aggregate).?;
3222 for (payload.data) |val| {
3223 if (val.anyUndef(mod)) return true;
3224 }
2034 pub fn anyUndef(val: Value, mod: *Module) !bool {
2035 if (val.ip_index == .none) return false;
2036 return switch (val.toIntern()) {
2037 .undef => true,
2038 else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
2039 .undef => true,
2040 .simple_value => |v| v == .undefined,
2041 .ptr => |ptr| switch (ptr.len) {
2042 .none => false,
2043 else => for (0..@intCast(usize, ptr.len.toValue().toUnsignedInt(mod))) |index| {
2044 if (try (try val.elemValue(mod, index)).anyUndef(mod)) break true;
2045 } else false,
2046 },
2047 .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| {
2048 const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i];
2049 if (try anyUndef(elem.toValue(), mod)) break true;
2050 } else false,
2051 else => false,
32252052 },
3226
3227 .undef => return true,
3228 else => {},
3229 }
3230
3231 return false;
2053 };
32322054 }
32332055
32342056 /// Asserts the value is not undefined and not unreachable.
3235 /// Integer value 0 is considered null because of C pointers.
3236 pub fn isNull(self: Value) bool {
3237 return switch (self.tag()) {
3238 .null_value => true,
3239 .opt_payload => false,
3240
3241 // If it's not one of those two tags then it must be a C pointer value,
3242 // in which case the value 0 is null and other values are non-null.
3243
3244 .zero,
3245 .bool_false,
3246 .the_only_possible_value,
3247 => true,
3248
3249 .one,
3250 .bool_true,
3251 => false,
3252
3253 .int_u64,
3254 .int_i64,
3255 .int_big_positive,
3256 .int_big_negative,
3257 => self.orderAgainstZero().compare(.eq),
3258
2057 /// C pointers with an integer value of 0 are also considered null.
2058 pub fn isNull(val: Value, mod: *Module) bool {
2059 return switch (val.toIntern()) {
32592060 .undef => unreachable,
32602061 .unreachable_value => unreachable,
3261 .inferred_alloc => unreachable,
3262 .inferred_alloc_comptime => unreachable,
3263
3264 else => false,
2062 .null_value => true,
2063 else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2064 .undef => unreachable,
2065 .ptr => |ptr| switch (ptr.addr) {
2066 .int => {
2067 var buf: BigIntSpace = undefined;
2068 return val.toBigInt(&buf, mod).eqZero();
2069 },
2070 else => false,
2071 },
2072 .opt => |opt| opt.val == .none,
2073 else => false,
2074 },
32652075 };
32662076 }
32672077
3268 /// Valid only for error (union) types. Asserts the value is not undefined and not
3269 /// unreachable. For error unions, prefer `errorUnionIsPayload` to find out whether
3270 /// something is an error or not because it works without having to figure out the
3271 /// string.
3272 pub fn getError(self: Value) ?[]const u8 {
3273 return switch (self.tag()) {
3274 .@"error" => self.castTag(.@"error").?.data.name,
3275 .int_u64 => @panic("TODO"),
3276 .int_i64 => @panic("TODO"),
3277 .int_big_positive => @panic("TODO"),
3278 .int_big_negative => @panic("TODO"),
3279 .one => @panic("TODO"),
3280 .undef => unreachable,
3281 .unreachable_value => unreachable,
3282 .inferred_alloc => unreachable,
3283 .inferred_alloc_comptime => unreachable,
3284
3285 else => null,
2078 /// Valid only for error (union) types. Asserts the value is not undefined and not unreachable.
2079 pub fn getErrorName(val: Value, mod: *const Module) InternPool.OptionalNullTerminatedString {
2080 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2081 .err => |err| err.name.toOptional(),
2082 .error_union => |error_union| switch (error_union.val) {
2083 .err_name => |err_name| err_name.toOptional(),
2084 .payload => .none,
2085 },
2086 else => unreachable,
32862087 };
32872088 }
32882089
2090 pub fn getErrorInt(val: Value, mod: *const Module) Module.ErrorInt {
2091 return if (getErrorName(val, mod).unwrap()) |err_name|
2092 @intCast(Module.ErrorInt, mod.global_error_set.getIndex(err_name).?)
2093 else
2094 0;
2095 }
2096
32892097 /// Assumes the type is an error union. Returns true if and only if the value is
32902098 /// the error union payload, not an error.
3291 pub fn errorUnionIsPayload(val: Value) bool {
3292 return switch (val.tag()) {
3293 .eu_payload => true,
3294 else => false,
3295
3296 .undef => unreachable,
3297 .inferred_alloc => unreachable,
3298 .inferred_alloc_comptime => unreachable,
3299 };
2099 pub fn errorUnionIsPayload(val: Value, mod: *const Module) bool {
2100 return mod.intern_pool.indexToKey(val.toIntern()).error_union.val == .payload;
33002101 }
33012102
33022103 /// Value of the optional, null if optional has no payload.
3303 pub fn optionalValue(val: Value) ?Value {
3304 if (val.isNull()) return null;
3305
3306 // Valid for optional representation to be the direct value
3307 // and not use opt_payload.
3308 return if (val.castTag(.opt_payload)) |p| p.data else val;
2104 pub fn optionalValue(val: Value, mod: *const Module) ?Value {
2105 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2106 .opt => |opt| switch (opt.val) {
2107 .none => null,
2108 else => |payload| payload.toValue(),
2109 },
2110 .ptr => val,
2111 else => unreachable,
2112 };
33092113 }
33102114
33112115 /// Valid for all types. Asserts the value is not undefined.
3312 pub fn isFloat(self: Value) bool {
3313 return switch (self.tag()) {
2116 pub fn isFloat(self: Value, mod: *const Module) bool {
2117 return switch (self.toIntern()) {
33142118 .undef => unreachable,
3315 .inferred_alloc => unreachable,
3316 .inferred_alloc_comptime => unreachable,
3317
3318 .float_16,
3319 .float_32,
3320 .float_64,
3321 .float_80,
3322 .float_128,
3323 => true,
3324 else => false,
2119 else => switch (mod.intern_pool.indexToKey(self.toIntern())) {
2120 .undef => unreachable,
2121 .float => true,
2122 else => false,
2123 },
33252124 };
33262125 }
33272126
......@@ -3333,79 +2132,59 @@ pub const Value = extern union {
33332132 }
33342133
33352134 pub fn intToFloatAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
3336 const target = mod.getTarget();
3337 if (int_ty.zigTypeTag() == .Vector) {
3338 const result_data = try arena.alloc(Value, int_ty.vectorLen());
2135 if (int_ty.zigTypeTag(mod) == .Vector) {
2136 const result_data = try arena.alloc(InternPool.Index, int_ty.vectorLen(mod));
2137 const scalar_ty = float_ty.scalarType(mod);
33392138 for (result_data, 0..) |*scalar, i| {
3340 var buf: Value.ElemValueBuffer = undefined;
3341 const elem_val = val.elemValueBuffer(mod, i, &buf);
3342 scalar.* = try intToFloatScalar(elem_val, arena, float_ty.scalarType(), target, opt_sema);
2139 const elem_val = try val.elemValue(mod, i);
2140 scalar.* = try (try intToFloatScalar(elem_val, scalar_ty, mod, opt_sema)).intern(scalar_ty, mod);
33432141 }
3344 return Value.Tag.aggregate.create(arena, result_data);
2142 return (try mod.intern(.{ .aggregate = .{
2143 .ty = float_ty.toIntern(),
2144 .storage = .{ .elems = result_data },
2145 } })).toValue();
33452146 }
3346 return intToFloatScalar(val, arena, float_ty, target, opt_sema);
2147 return intToFloatScalar(val, float_ty, mod, opt_sema);
33472148 }
33482149
3349 pub fn intToFloatScalar(val: Value, arena: Allocator, float_ty: Type, target: Target, opt_sema: ?*Sema) !Value {
3350 switch (val.tag()) {
3351 .undef, .zero, .one => return val,
3352 .the_only_possible_value => return Value.initTag(.zero), // for i0, u0
3353 .int_u64 => {
3354 return intToFloatInner(val.castTag(.int_u64).?.data, arena, float_ty, target);
3355 },
3356 .int_i64 => {
3357 return intToFloatInner(val.castTag(.int_i64).?.data, arena, float_ty, target);
3358 },
3359 .int_big_positive => {
3360 const limbs = val.castTag(.int_big_positive).?.data;
3361 const float = bigIntToFloat(limbs, true);
3362 return floatToValue(float, arena, float_ty, target);
3363 },
3364 .int_big_negative => {
3365 const limbs = val.castTag(.int_big_negative).?.data;
3366 const float = bigIntToFloat(limbs, false);
3367 return floatToValue(float, arena, float_ty, target);
3368 },
3369 .lazy_align => {
3370 const ty = val.castTag(.lazy_align).?.data;
3371 if (opt_sema) |sema| {
3372 return intToFloatInner((try ty.abiAlignmentAdvanced(target, .{ .sema = sema })).scalar, arena, float_ty, target);
2150 pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
2151 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2152 .undef => (try mod.intern(.{ .undef = float_ty.toIntern() })).toValue(),
2153 .int => |int| switch (int.storage) {
2154 .big_int => |big_int| {
2155 const float = bigIntToFloat(big_int.limbs, big_int.positive);
2156 return mod.floatValue(float_ty, float);
2157 },
2158 inline .u64, .i64 => |x| intToFloatInner(x, float_ty, mod),
2159 .lazy_align => |ty| if (opt_sema) |sema| {
2160 return intToFloatInner((try ty.toType().abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
33732161 } else {
3374 return intToFloatInner(ty.abiAlignment(target), arena, float_ty, target);
3375 }
3376 },
3377 .lazy_size => {
3378 const ty = val.castTag(.lazy_size).?.data;
3379 if (opt_sema) |sema| {
3380 return intToFloatInner((try ty.abiSizeAdvanced(target, .{ .sema = sema })).scalar, arena, float_ty, target);
2162 return intToFloatInner(ty.toType().abiAlignment(mod), float_ty, mod);
2163 },
2164 .lazy_size => |ty| if (opt_sema) |sema| {
2165 return intToFloatInner((try ty.toType().abiSizeAdvanced(mod, .{ .sema = sema })).scalar, float_ty, mod);
33812166 } else {
3382 return intToFloatInner(ty.abiSize(target), arena, float_ty, target);
3383 }
2167 return intToFloatInner(ty.toType().abiSize(mod), float_ty, mod);
2168 },
33842169 },
33852170 else => unreachable,
3386 }
3387 }
3388
3389 fn intToFloatInner(x: anytype, arena: Allocator, dest_ty: Type, target: Target) !Value {
3390 switch (dest_ty.floatBits(target)) {
3391 16 => return Value.Tag.float_16.create(arena, @intToFloat(f16, x)),
3392 32 => return Value.Tag.float_32.create(arena, @intToFloat(f32, x)),
3393 64 => return Value.Tag.float_64.create(arena, @intToFloat(f64, x)),
3394 80 => return Value.Tag.float_80.create(arena, @intToFloat(f80, x)),
3395 128 => return Value.Tag.float_128.create(arena, @intToFloat(f128, x)),
3396 else => unreachable,
3397 }
2171 };
33982172 }
33992173
3400 pub fn floatToValue(float: f128, arena: Allocator, dest_ty: Type, target: Target) !Value {
3401 switch (dest_ty.floatBits(target)) {
3402 16 => return Value.Tag.float_16.create(arena, @floatCast(f16, float)),
3403 32 => return Value.Tag.float_32.create(arena, @floatCast(f32, float)),
3404 64 => return Value.Tag.float_64.create(arena, @floatCast(f64, float)),
3405 80 => return Value.Tag.float_80.create(arena, @floatCast(f80, float)),
3406 128 => return Value.Tag.float_128.create(arena, float),
2174 fn intToFloatInner(x: anytype, dest_ty: Type, mod: *Module) !Value {
2175 const target = mod.getTarget();
2176 const storage: InternPool.Key.Float.Storage = switch (dest_ty.floatBits(target)) {
2177 16 => .{ .f16 = @intToFloat(f16, x) },
2178 32 => .{ .f32 = @intToFloat(f32, x) },
2179 64 => .{ .f64 = @intToFloat(f64, x) },
2180 80 => .{ .f80 = @intToFloat(f80, x) },
2181 128 => .{ .f128 = @intToFloat(f128, x) },
34072182 else => unreachable,
3408 }
2183 };
2184 return (try mod.intern(.{ .float = .{
2185 .ty = dest_ty.toIntern(),
2186 .storage = storage,
2187 } })).toValue();
34092188 }
34102189
34112190 fn calcLimbLenFloat(scalar: anytype) usize {
......@@ -3422,22 +2201,6 @@ pub const Value = extern union {
34222201 wrapped_result: Value,
34232202 };
34242203
3425 pub fn fromBigInt(arena: Allocator, big_int: BigIntConst) !Value {
3426 if (big_int.positive) {
3427 if (big_int.to(u64)) |x| {
3428 return Value.Tag.int_u64.create(arena, x);
3429 } else |_| {
3430 return Value.Tag.int_big_positive.create(arena, big_int.limbs);
3431 }
3432 } else {
3433 if (big_int.to(i64)) |x| {
3434 return Value.Tag.int_i64.create(arena, x);
3435 } else |_| {
3436 return Value.Tag.int_big_negative.create(arena, big_int.limbs);
3437 }
3438 }
3439 }
3440
34412204 /// Supports (vectors of) integers only; asserts neither operand is undefined.
34422205 pub fn intAddSat(
34432206 lhs: Value,
......@@ -3446,19 +2209,20 @@ pub const Value = extern union {
34462209 arena: Allocator,
34472210 mod: *Module,
34482211 ) !Value {
3449 const target = mod.getTarget();
3450 if (ty.zigTypeTag() == .Vector) {
3451 const result_data = try arena.alloc(Value, ty.vectorLen());
2212 if (ty.zigTypeTag(mod) == .Vector) {
2213 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2214 const scalar_ty = ty.scalarType(mod);
34522215 for (result_data, 0..) |*scalar, i| {
3453 var lhs_buf: Value.ElemValueBuffer = undefined;
3454 var rhs_buf: Value.ElemValueBuffer = undefined;
3455 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3456 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3457 scalar.* = try intAddSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
2216 const lhs_elem = try lhs.elemValue(mod, i);
2217 const rhs_elem = try rhs.elemValue(mod, i);
2218 scalar.* = try (try intAddSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
34582219 }
3459 return Value.Tag.aggregate.create(arena, result_data);
2220 return (try mod.intern(.{ .aggregate = .{
2221 .ty = ty.toIntern(),
2222 .storage = .{ .elems = result_data },
2223 } })).toValue();
34602224 }
3461 return intAddSatScalar(lhs, rhs, ty, arena, target);
2225 return intAddSatScalar(lhs, rhs, ty, arena, mod);
34622226 }
34632227
34642228 /// Supports integers only; asserts neither operand is undefined.
......@@ -3467,24 +2231,24 @@ pub const Value = extern union {
34672231 rhs: Value,
34682232 ty: Type,
34692233 arena: Allocator,
3470 target: Target,
2234 mod: *Module,
34712235 ) !Value {
3472 assert(!lhs.isUndef());
3473 assert(!rhs.isUndef());
2236 assert(!lhs.isUndef(mod));
2237 assert(!rhs.isUndef(mod));
34742238
3475 const info = ty.intInfo(target);
2239 const info = ty.intInfo(mod);
34762240
34772241 var lhs_space: Value.BigIntSpace = undefined;
34782242 var rhs_space: Value.BigIntSpace = undefined;
3479 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3480 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2243 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2244 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
34812245 const limbs = try arena.alloc(
34822246 std.math.big.Limb,
34832247 std.math.big.int.calcTwosCompLimbCount(info.bits),
34842248 );
34852249 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
34862250 result_bigint.addSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
3487 return fromBigInt(arena, result_bigint.toConst());
2251 return mod.intValue_big(ty, result_bigint.toConst());
34882252 }
34892253
34902254 /// Supports (vectors of) integers only; asserts neither operand is undefined.
......@@ -3495,19 +2259,20 @@ pub const Value = extern union {
34952259 arena: Allocator,
34962260 mod: *Module,
34972261 ) !Value {
3498 const target = mod.getTarget();
3499 if (ty.zigTypeTag() == .Vector) {
3500 const result_data = try arena.alloc(Value, ty.vectorLen());
2262 if (ty.zigTypeTag(mod) == .Vector) {
2263 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2264 const scalar_ty = ty.scalarType(mod);
35012265 for (result_data, 0..) |*scalar, i| {
3502 var lhs_buf: Value.ElemValueBuffer = undefined;
3503 var rhs_buf: Value.ElemValueBuffer = undefined;
3504 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3505 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3506 scalar.* = try intSubSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
2266 const lhs_elem = try lhs.elemValue(mod, i);
2267 const rhs_elem = try rhs.elemValue(mod, i);
2268 scalar.* = try (try intSubSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
35072269 }
3508 return Value.Tag.aggregate.create(arena, result_data);
2270 return (try mod.intern(.{ .aggregate = .{
2271 .ty = ty.toIntern(),
2272 .storage = .{ .elems = result_data },
2273 } })).toValue();
35092274 }
3510 return intSubSatScalar(lhs, rhs, ty, arena, target);
2275 return intSubSatScalar(lhs, rhs, ty, arena, mod);
35112276 }
35122277
35132278 /// Supports integers only; asserts neither operand is undefined.
......@@ -3516,24 +2281,24 @@ pub const Value = extern union {
35162281 rhs: Value,
35172282 ty: Type,
35182283 arena: Allocator,
3519 target: Target,
2284 mod: *Module,
35202285 ) !Value {
3521 assert(!lhs.isUndef());
3522 assert(!rhs.isUndef());
2286 assert(!lhs.isUndef(mod));
2287 assert(!rhs.isUndef(mod));
35232288
3524 const info = ty.intInfo(target);
2289 const info = ty.intInfo(mod);
35252290
35262291 var lhs_space: Value.BigIntSpace = undefined;
35272292 var rhs_space: Value.BigIntSpace = undefined;
3528 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3529 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2293 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2294 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
35302295 const limbs = try arena.alloc(
35312296 std.math.big.Limb,
35322297 std.math.big.int.calcTwosCompLimbCount(info.bits),
35332298 );
35342299 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
35352300 result_bigint.subSat(lhs_bigint, rhs_bigint, info.signedness, info.bits);
3536 return fromBigInt(arena, result_bigint.toConst());
2301 return mod.intValue_big(ty, result_bigint.toConst());
35372302 }
35382303
35392304 pub fn intMulWithOverflow(
......@@ -3543,25 +2308,30 @@ pub const Value = extern union {
35432308 arena: Allocator,
35442309 mod: *Module,
35452310 ) !OverflowArithmeticResult {
3546 const target = mod.getTarget();
3547 if (ty.zigTypeTag() == .Vector) {
3548 const overflowed_data = try arena.alloc(Value, ty.vectorLen());
3549 const result_data = try arena.alloc(Value, ty.vectorLen());
3550 for (result_data, 0..) |*scalar, i| {
3551 var lhs_buf: Value.ElemValueBuffer = undefined;
3552 var rhs_buf: Value.ElemValueBuffer = undefined;
3553 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3554 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3555 const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
3556 overflowed_data[i] = of_math_result.overflow_bit;
3557 scalar.* = of_math_result.wrapped_result;
2311 if (ty.zigTypeTag(mod) == .Vector) {
2312 const vec_len = ty.vectorLen(mod);
2313 const overflowed_data = try arena.alloc(InternPool.Index, vec_len);
2314 const result_data = try arena.alloc(InternPool.Index, vec_len);
2315 const scalar_ty = ty.scalarType(mod);
2316 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
2317 const lhs_elem = try lhs.elemValue(mod, i);
2318 const rhs_elem = try rhs.elemValue(mod, i);
2319 const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod);
2320 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
2321 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
35582322 }
35592323 return OverflowArithmeticResult{
3560 .overflow_bit = try Value.Tag.aggregate.create(arena, overflowed_data),
3561 .wrapped_result = try Value.Tag.aggregate.create(arena, result_data),
2324 .overflow_bit = (try mod.intern(.{ .aggregate = .{
2325 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
2326 .storage = .{ .elems = overflowed_data },
2327 } })).toValue(),
2328 .wrapped_result = (try mod.intern(.{ .aggregate = .{
2329 .ty = ty.toIntern(),
2330 .storage = .{ .elems = result_data },
2331 } })).toValue(),
35622332 };
35632333 }
3564 return intMulWithOverflowScalar(lhs, rhs, ty, arena, target);
2334 return intMulWithOverflowScalar(lhs, rhs, ty, arena, mod);
35652335 }
35662336
35672337 pub fn intMulWithOverflowScalar(
......@@ -3569,14 +2339,14 @@ pub const Value = extern union {
35692339 rhs: Value,
35702340 ty: Type,
35712341 arena: Allocator,
3572 target: Target,
2342 mod: *Module,
35732343 ) !OverflowArithmeticResult {
3574 const info = ty.intInfo(target);
2344 const info = ty.intInfo(mod);
35752345
35762346 var lhs_space: Value.BigIntSpace = undefined;
35772347 var rhs_space: Value.BigIntSpace = undefined;
3578 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3579 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2348 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2349 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
35802350 const limbs = try arena.alloc(
35812351 std.math.big.Limb,
35822352 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
......@@ -3594,8 +2364,8 @@ pub const Value = extern union {
35942364 }
35952365
35962366 return OverflowArithmeticResult{
3597 .overflow_bit = boolToInt(overflowed),
3598 .wrapped_result = try fromBigInt(arena, result_bigint.toConst()),
2367 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
2368 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
35992369 };
36002370 }
36012371
......@@ -3607,16 +2377,18 @@ pub const Value = extern union {
36072377 arena: Allocator,
36082378 mod: *Module,
36092379 ) !Value {
3610 if (ty.zigTypeTag() == .Vector) {
3611 const result_data = try arena.alloc(Value, ty.vectorLen());
2380 if (ty.zigTypeTag(mod) == .Vector) {
2381 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2382 const scalar_ty = ty.scalarType(mod);
36122383 for (result_data, 0..) |*scalar, i| {
3613 var lhs_buf: Value.ElemValueBuffer = undefined;
3614 var rhs_buf: Value.ElemValueBuffer = undefined;
3615 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3616 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3617 scalar.* = try numberMulWrapScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod);
2384 const lhs_elem = try lhs.elemValue(mod, i);
2385 const rhs_elem = try rhs.elemValue(mod, i);
2386 scalar.* = try (try numberMulWrapScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
36182387 }
3619 return Value.Tag.aggregate.create(arena, result_data);
2388 return (try mod.intern(.{ .aggregate = .{
2389 .ty = ty.toIntern(),
2390 .storage = .{ .elems = result_data },
2391 } })).toValue();
36202392 }
36212393 return numberMulWrapScalar(lhs, rhs, ty, arena, mod);
36222394 }
......@@ -3629,10 +2401,10 @@ pub const Value = extern union {
36292401 arena: Allocator,
36302402 mod: *Module,
36312403 ) !Value {
3632 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
2404 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return Value.undef;
36332405
3634 if (ty.zigTypeTag() == .ComptimeInt) {
3635 return intMul(lhs, rhs, ty, arena, mod);
2406 if (ty.zigTypeTag(mod) == .ComptimeInt) {
2407 return intMul(lhs, rhs, ty, undefined, arena, mod);
36362408 }
36372409
36382410 if (ty.isAnyFloat()) {
......@@ -3651,19 +2423,20 @@ pub const Value = extern union {
36512423 arena: Allocator,
36522424 mod: *Module,
36532425 ) !Value {
3654 const target = mod.getTarget();
3655 if (ty.zigTypeTag() == .Vector) {
3656 const result_data = try arena.alloc(Value, ty.vectorLen());
2426 if (ty.zigTypeTag(mod) == .Vector) {
2427 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2428 const scalar_ty = ty.scalarType(mod);
36572429 for (result_data, 0..) |*scalar, i| {
3658 var lhs_buf: Value.ElemValueBuffer = undefined;
3659 var rhs_buf: Value.ElemValueBuffer = undefined;
3660 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3661 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3662 scalar.* = try intMulSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
2430 const lhs_elem = try lhs.elemValue(mod, i);
2431 const rhs_elem = try rhs.elemValue(mod, i);
2432 scalar.* = try (try intMulSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
36632433 }
3664 return Value.Tag.aggregate.create(arena, result_data);
2434 return (try mod.intern(.{ .aggregate = .{
2435 .ty = ty.toIntern(),
2436 .storage = .{ .elems = result_data },
2437 } })).toValue();
36652438 }
3666 return intMulSatScalar(lhs, rhs, ty, arena, target);
2439 return intMulSatScalar(lhs, rhs, ty, arena, mod);
36672440 }
36682441
36692442 /// Supports (vectors of) integers only; asserts neither operand is undefined.
......@@ -3672,17 +2445,17 @@ pub const Value = extern union {
36722445 rhs: Value,
36732446 ty: Type,
36742447 arena: Allocator,
3675 target: Target,
2448 mod: *Module,
36762449 ) !Value {
3677 assert(!lhs.isUndef());
3678 assert(!rhs.isUndef());
2450 assert(!lhs.isUndef(mod));
2451 assert(!rhs.isUndef(mod));
36792452
3680 const info = ty.intInfo(target);
2453 const info = ty.intInfo(mod);
36812454
36822455 var lhs_space: Value.BigIntSpace = undefined;
36832456 var rhs_space: Value.BigIntSpace = undefined;
3684 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3685 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2457 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2458 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
36862459 const limbs = try arena.alloc(
36872460 std.math.big.Limb,
36882461 std.math.max(
......@@ -3698,28 +2471,28 @@ pub const Value = extern union {
36982471 );
36992472 result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, arena);
37002473 result_bigint.saturate(result_bigint.toConst(), info.signedness, info.bits);
3701 return fromBigInt(arena, result_bigint.toConst());
2474 return mod.intValue_big(ty, result_bigint.toConst());
37022475 }
37032476
37042477 /// Supports both floats and ints; handles undefined.
3705 pub fn numberMax(lhs: Value, rhs: Value, target: Target) Value {
3706 if (lhs.isUndef() or rhs.isUndef()) return undef;
3707 if (lhs.isNan()) return rhs;
3708 if (rhs.isNan()) return lhs;
2478 pub fn numberMax(lhs: Value, rhs: Value, mod: *Module) Value {
2479 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return undef;
2480 if (lhs.isNan(mod)) return rhs;
2481 if (rhs.isNan(mod)) return lhs;
37092482
3710 return switch (order(lhs, rhs, target)) {
2483 return switch (order(lhs, rhs, mod)) {
37112484 .lt => rhs,
37122485 .gt, .eq => lhs,
37132486 };
37142487 }
37152488
37162489 /// Supports both floats and ints; handles undefined.
3717 pub fn numberMin(lhs: Value, rhs: Value, target: Target) Value {
3718 if (lhs.isUndef() or rhs.isUndef()) return undef;
3719 if (lhs.isNan()) return rhs;
3720 if (rhs.isNan()) return lhs;
2490 pub fn numberMin(lhs: Value, rhs: Value, mod: *Module) Value {
2491 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return undef;
2492 if (lhs.isNan(mod)) return rhs;
2493 if (rhs.isNan(mod)) return lhs;
37212494
3722 return switch (order(lhs, rhs, target)) {
2495 return switch (order(lhs, rhs, mod)) {
37232496 .lt => lhs,
37242497 .gt, .eq => rhs,
37252498 };
......@@ -3727,24 +2500,27 @@ pub const Value = extern union {
37272500
37282501 /// operands must be (vectors of) integers; handles undefined scalars.
37292502 pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3730 const target = mod.getTarget();
3731 if (ty.zigTypeTag() == .Vector) {
3732 const result_data = try arena.alloc(Value, ty.vectorLen());
2503 if (ty.zigTypeTag(mod) == .Vector) {
2504 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2505 const scalar_ty = ty.scalarType(mod);
37332506 for (result_data, 0..) |*scalar, i| {
3734 var buf: Value.ElemValueBuffer = undefined;
3735 const elem_val = val.elemValueBuffer(mod, i, &buf);
3736 scalar.* = try bitwiseNotScalar(elem_val, ty.scalarType(), arena, target);
2507 const elem_val = try val.elemValue(mod, i);
2508 scalar.* = try (try bitwiseNotScalar(elem_val, scalar_ty, arena, mod)).intern(scalar_ty, mod);
37372509 }
3738 return Value.Tag.aggregate.create(arena, result_data);
2510 return (try mod.intern(.{ .aggregate = .{
2511 .ty = ty.toIntern(),
2512 .storage = .{ .elems = result_data },
2513 } })).toValue();
37392514 }
3740 return bitwiseNotScalar(val, ty, arena, target);
2515 return bitwiseNotScalar(val, ty, arena, mod);
37412516 }
37422517
37432518 /// operands must be integers; handles undefined.
3744 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, target: Target) !Value {
3745 if (val.isUndef()) return Value.initTag(.undef);
2519 pub fn bitwiseNotScalar(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2520 if (val.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2521 if (ty.toIntern() == .bool_type) return makeBool(!val.toBool());
37462522
3747 const info = ty.intInfo(target);
2523 const info = ty.intInfo(mod);
37482524
37492525 if (info.bits == 0) {
37502526 return val;
......@@ -3753,7 +2529,7 @@ pub const Value = extern union {
37532529 // TODO is this a performance issue? maybe we should try the operation without
37542530 // resorting to BigInt first.
37552531 var val_space: Value.BigIntSpace = undefined;
3756 const val_bigint = val.toBigInt(&val_space, target);
2532 const val_bigint = val.toBigInt(&val_space, mod);
37572533 const limbs = try arena.alloc(
37582534 std.math.big.Limb,
37592535 std.math.big.int.calcTwosCompLimbCount(info.bits),
......@@ -3761,36 +2537,38 @@ pub const Value = extern union {
37612537
37622538 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
37632539 result_bigint.bitNotWrap(val_bigint, info.signedness, info.bits);
3764 return fromBigInt(arena, result_bigint.toConst());
2540 return mod.intValue_big(ty, result_bigint.toConst());
37652541 }
37662542
37672543 /// operands must be (vectors of) integers; handles undefined scalars.
37682544 pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3769 const target = mod.getTarget();
3770 if (ty.zigTypeTag() == .Vector) {
3771 const result_data = try allocator.alloc(Value, ty.vectorLen());
2545 if (ty.zigTypeTag(mod) == .Vector) {
2546 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2547 const scalar_ty = ty.scalarType(mod);
37722548 for (result_data, 0..) |*scalar, i| {
3773 var lhs_buf: Value.ElemValueBuffer = undefined;
3774 var rhs_buf: Value.ElemValueBuffer = undefined;
3775 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3776 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3777 scalar.* = try bitwiseAndScalar(lhs_elem, rhs_elem, allocator, target);
2549 const lhs_elem = try lhs.elemValue(mod, i);
2550 const rhs_elem = try rhs.elemValue(mod, i);
2551 scalar.* = try (try bitwiseAndScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
37782552 }
3779 return Value.Tag.aggregate.create(allocator, result_data);
2553 return (try mod.intern(.{ .aggregate = .{
2554 .ty = ty.toIntern(),
2555 .storage = .{ .elems = result_data },
2556 } })).toValue();
37802557 }
3781 return bitwiseAndScalar(lhs, rhs, allocator, target);
2558 return bitwiseAndScalar(lhs, rhs, ty, allocator, mod);
37822559 }
37832560
37842561 /// operands must be integers; handles undefined.
3785 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value {
3786 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
2562 pub fn bitwiseAndScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2563 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2564 if (ty.toIntern() == .bool_type) return makeBool(lhs.toBool() and rhs.toBool());
37872565
37882566 // TODO is this a performance issue? maybe we should try the operation without
37892567 // resorting to BigInt first.
37902568 var lhs_space: Value.BigIntSpace = undefined;
37912569 var rhs_space: Value.BigIntSpace = undefined;
3792 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3793 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2570 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2571 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
37942572 const limbs = try arena.alloc(
37952573 std.math.big.Limb,
37962574 // + 1 for negatives
......@@ -3798,102 +2576,104 @@ pub const Value = extern union {
37982576 );
37992577 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
38002578 result_bigint.bitAnd(lhs_bigint, rhs_bigint);
3801 return fromBigInt(arena, result_bigint.toConst());
2579 return mod.intValue_big(ty, result_bigint.toConst());
38022580 }
38032581
38042582 /// operands must be (vectors of) integers; handles undefined scalars.
38052583 pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3806 if (ty.zigTypeTag() == .Vector) {
3807 const result_data = try arena.alloc(Value, ty.vectorLen());
2584 if (ty.zigTypeTag(mod) == .Vector) {
2585 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
2586 const scalar_ty = ty.scalarType(mod);
38082587 for (result_data, 0..) |*scalar, i| {
3809 var lhs_buf: Value.ElemValueBuffer = undefined;
3810 var rhs_buf: Value.ElemValueBuffer = undefined;
3811 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3812 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3813 scalar.* = try bitwiseNandScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod);
2588 const lhs_elem = try lhs.elemValue(mod, i);
2589 const rhs_elem = try rhs.elemValue(mod, i);
2590 scalar.* = try (try bitwiseNandScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
38142591 }
3815 return Value.Tag.aggregate.create(arena, result_data);
2592 return (try mod.intern(.{ .aggregate = .{
2593 .ty = ty.toIntern(),
2594 .storage = .{ .elems = result_data },
2595 } })).toValue();
38162596 }
38172597 return bitwiseNandScalar(lhs, rhs, ty, arena, mod);
38182598 }
38192599
38202600 /// operands must be integers; handles undefined.
38212601 pub fn bitwiseNandScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
3822 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
2602 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2603 if (ty.toIntern() == .bool_type) return makeBool(!(lhs.toBool() and rhs.toBool()));
38232604
38242605 const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
3825
3826 const all_ones = if (ty.isSignedInt())
3827 try Value.Tag.int_i64.create(arena, -1)
3828 else
3829 try ty.maxInt(arena, mod.getTarget());
3830
2606 const all_ones = if (ty.isSignedInt(mod)) try mod.intValue(ty, -1) else try ty.maxIntScalar(mod, ty);
38312607 return bitwiseXor(anded, all_ones, ty, arena, mod);
38322608 }
38332609
38342610 /// operands must be (vectors of) integers; handles undefined scalars.
38352611 pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3836 const target = mod.getTarget();
3837 if (ty.zigTypeTag() == .Vector) {
3838 const result_data = try allocator.alloc(Value, ty.vectorLen());
2612 if (ty.zigTypeTag(mod) == .Vector) {
2613 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2614 const scalar_ty = ty.scalarType(mod);
38392615 for (result_data, 0..) |*scalar, i| {
3840 var lhs_buf: Value.ElemValueBuffer = undefined;
3841 var rhs_buf: Value.ElemValueBuffer = undefined;
3842 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3843 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3844 scalar.* = try bitwiseOrScalar(lhs_elem, rhs_elem, allocator, target);
2616 const lhs_elem = try lhs.elemValue(mod, i);
2617 const rhs_elem = try rhs.elemValue(mod, i);
2618 scalar.* = try (try bitwiseOrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
38452619 }
3846 return Value.Tag.aggregate.create(allocator, result_data);
2620 return (try mod.intern(.{ .aggregate = .{
2621 .ty = ty.toIntern(),
2622 .storage = .{ .elems = result_data },
2623 } })).toValue();
38472624 }
3848 return bitwiseOrScalar(lhs, rhs, allocator, target);
2625 return bitwiseOrScalar(lhs, rhs, ty, allocator, mod);
38492626 }
38502627
38512628 /// operands must be integers; handles undefined.
3852 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value {
3853 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
2629 pub fn bitwiseOrScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2630 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2631 if (ty.toIntern() == .bool_type) return makeBool(lhs.toBool() or rhs.toBool());
38542632
38552633 // TODO is this a performance issue? maybe we should try the operation without
38562634 // resorting to BigInt first.
38572635 var lhs_space: Value.BigIntSpace = undefined;
38582636 var rhs_space: Value.BigIntSpace = undefined;
3859 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3860 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2637 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2638 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
38612639 const limbs = try arena.alloc(
38622640 std.math.big.Limb,
38632641 std.math.max(lhs_bigint.limbs.len, rhs_bigint.limbs.len),
38642642 );
38652643 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
38662644 result_bigint.bitOr(lhs_bigint, rhs_bigint);
3867 return fromBigInt(arena, result_bigint.toConst());
2645 return mod.intValue_big(ty, result_bigint.toConst());
38682646 }
38692647
38702648 /// operands must be (vectors of) integers; handles undefined scalars.
38712649 pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3872 const target = mod.getTarget();
3873 if (ty.zigTypeTag() == .Vector) {
3874 const result_data = try allocator.alloc(Value, ty.vectorLen());
2650 if (ty.zigTypeTag(mod) == .Vector) {
2651 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2652 const scalar_ty = ty.scalarType(mod);
38752653 for (result_data, 0..) |*scalar, i| {
3876 var lhs_buf: Value.ElemValueBuffer = undefined;
3877 var rhs_buf: Value.ElemValueBuffer = undefined;
3878 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3879 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3880 scalar.* = try bitwiseXorScalar(lhs_elem, rhs_elem, allocator, target);
2654 const lhs_elem = try lhs.elemValue(mod, i);
2655 const rhs_elem = try rhs.elemValue(mod, i);
2656 scalar.* = try (try bitwiseXorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
38812657 }
3882 return Value.Tag.aggregate.create(allocator, result_data);
2658 return (try mod.intern(.{ .aggregate = .{
2659 .ty = ty.toIntern(),
2660 .storage = .{ .elems = result_data },
2661 } })).toValue();
38832662 }
3884 return bitwiseXorScalar(lhs, rhs, allocator, target);
2663 return bitwiseXorScalar(lhs, rhs, ty, allocator, mod);
38852664 }
38862665
38872666 /// operands must be integers; handles undefined.
3888 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, arena: Allocator, target: Target) !Value {
3889 if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
2667 pub fn bitwiseXorScalar(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Module) !Value {
2668 if (lhs.isUndef(mod) or rhs.isUndef(mod)) return (try mod.intern(.{ .undef = ty.toIntern() })).toValue();
2669 if (ty.toIntern() == .bool_type) return makeBool(lhs.toBool() != rhs.toBool());
38902670
38912671 // TODO is this a performance issue? maybe we should try the operation without
38922672 // resorting to BigInt first.
38932673 var lhs_space: Value.BigIntSpace = undefined;
38942674 var rhs_space: Value.BigIntSpace = undefined;
3895 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3896 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2675 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2676 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
38972677 const limbs = try arena.alloc(
38982678 std.math.big.Limb,
38992679 // + 1 for negatives
......@@ -3901,32 +2681,61 @@ pub const Value = extern union {
39012681 );
39022682 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
39032683 result_bigint.bitXor(lhs_bigint, rhs_bigint);
3904 return fromBigInt(arena, result_bigint.toConst());
2684 return mod.intValue_big(ty, result_bigint.toConst());
2685 }
2686
2687 /// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
2688 /// overflow_idx to the vector index the overflow was at (or 0 for a scalar).
2689 pub fn intDiv(lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize, allocator: Allocator, mod: *Module) !Value {
2690 var overflow: usize = undefined;
2691 return intDivInner(lhs, rhs, ty, &overflow, allocator, mod) catch |err| switch (err) {
2692 error.Overflow => {
2693 const is_vec = ty.isVector(mod);
2694 overflow_idx.* = if (is_vec) overflow else 0;
2695 const safe_ty = if (is_vec) try mod.vectorType(.{
2696 .len = ty.vectorLen(mod),
2697 .child = .comptime_int_type,
2698 }) else Type.comptime_int;
2699 return intDivInner(lhs, rhs, safe_ty, undefined, allocator, mod) catch |err1| switch (err1) {
2700 error.Overflow => unreachable,
2701 else => |e| return e,
2702 };
2703 },
2704 else => |e| return e,
2705 };
39052706 }
39062707
3907 pub fn intDiv(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3908 const target = mod.getTarget();
3909 if (ty.zigTypeTag() == .Vector) {
3910 const result_data = try allocator.alloc(Value, ty.vectorLen());
2708 fn intDivInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator: Allocator, mod: *Module) !Value {
2709 if (ty.zigTypeTag(mod) == .Vector) {
2710 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2711 const scalar_ty = ty.scalarType(mod);
39112712 for (result_data, 0..) |*scalar, i| {
3912 var lhs_buf: Value.ElemValueBuffer = undefined;
3913 var rhs_buf: Value.ElemValueBuffer = undefined;
3914 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3915 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3916 scalar.* = try intDivScalar(lhs_elem, rhs_elem, allocator, target);
2713 const lhs_elem = try lhs.elemValue(mod, i);
2714 const rhs_elem = try rhs.elemValue(mod, i);
2715 const val = intDivScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod) catch |err| switch (err) {
2716 error.Overflow => {
2717 overflow_idx.* = i;
2718 return error.Overflow;
2719 },
2720 else => |e| return e,
2721 };
2722 scalar.* = try val.intern(scalar_ty, mod);
39172723 }
3918 return Value.Tag.aggregate.create(allocator, result_data);
2724 return (try mod.intern(.{ .aggregate = .{
2725 .ty = ty.toIntern(),
2726 .storage = .{ .elems = result_data },
2727 } })).toValue();
39192728 }
3920 return intDivScalar(lhs, rhs, allocator, target);
2729 return intDivScalar(lhs, rhs, ty, allocator, mod);
39212730 }
39222731
3923 pub fn intDivScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
2732 pub fn intDivScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
39242733 // TODO is this a performance issue? maybe we should try the operation without
39252734 // resorting to BigInt first.
39262735 var lhs_space: Value.BigIntSpace = undefined;
39272736 var rhs_space: Value.BigIntSpace = undefined;
3928 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3929 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2737 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2738 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
39302739 const limbs_q = try allocator.alloc(
39312740 std.math.big.Limb,
39322741 lhs_bigint.limbs.len,
......@@ -3942,32 +2751,39 @@ pub const Value = extern union {
39422751 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
39432752 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
39442753 result_q.divTrunc(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
3945 return fromBigInt(allocator, result_q.toConst());
2754 if (ty.toIntern() != .comptime_int_type) {
2755 const info = ty.intInfo(mod);
2756 if (!result_q.toConst().fitsInTwosComp(info.signedness, info.bits)) {
2757 return error.Overflow;
2758 }
2759 }
2760 return mod.intValue_big(ty, result_q.toConst());
39462761 }
39472762
39482763 pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3949 const target = mod.getTarget();
3950 if (ty.zigTypeTag() == .Vector) {
3951 const result_data = try allocator.alloc(Value, ty.vectorLen());
2764 if (ty.zigTypeTag(mod) == .Vector) {
2765 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2766 const scalar_ty = ty.scalarType(mod);
39522767 for (result_data, 0..) |*scalar, i| {
3953 var lhs_buf: Value.ElemValueBuffer = undefined;
3954 var rhs_buf: Value.ElemValueBuffer = undefined;
3955 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3956 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3957 scalar.* = try intDivFloorScalar(lhs_elem, rhs_elem, allocator, target);
2768 const lhs_elem = try lhs.elemValue(mod, i);
2769 const rhs_elem = try rhs.elemValue(mod, i);
2770 scalar.* = try (try intDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
39582771 }
3959 return Value.Tag.aggregate.create(allocator, result_data);
2772 return (try mod.intern(.{ .aggregate = .{
2773 .ty = ty.toIntern(),
2774 .storage = .{ .elems = result_data },
2775 } })).toValue();
39602776 }
3961 return intDivFloorScalar(lhs, rhs, allocator, target);
2777 return intDivFloorScalar(lhs, rhs, ty, allocator, mod);
39622778 }
39632779
3964 pub fn intDivFloorScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
2780 pub fn intDivFloorScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
39652781 // TODO is this a performance issue? maybe we should try the operation without
39662782 // resorting to BigInt first.
39672783 var lhs_space: Value.BigIntSpace = undefined;
39682784 var rhs_space: Value.BigIntSpace = undefined;
3969 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
3970 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2785 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2786 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
39712787 const limbs_q = try allocator.alloc(
39722788 std.math.big.Limb,
39732789 lhs_bigint.limbs.len,
......@@ -3983,32 +2799,33 @@ pub const Value = extern union {
39832799 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
39842800 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
39852801 result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
3986 return fromBigInt(allocator, result_q.toConst());
2802 return mod.intValue_big(ty, result_q.toConst());
39872803 }
39882804
39892805 pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
3990 const target = mod.getTarget();
3991 if (ty.zigTypeTag() == .Vector) {
3992 const result_data = try allocator.alloc(Value, ty.vectorLen());
2806 if (ty.zigTypeTag(mod) == .Vector) {
2807 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2808 const scalar_ty = ty.scalarType(mod);
39932809 for (result_data, 0..) |*scalar, i| {
3994 var lhs_buf: Value.ElemValueBuffer = undefined;
3995 var rhs_buf: Value.ElemValueBuffer = undefined;
3996 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
3997 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
3998 scalar.* = try intModScalar(lhs_elem, rhs_elem, allocator, target);
2810 const lhs_elem = try lhs.elemValue(mod, i);
2811 const rhs_elem = try rhs.elemValue(mod, i);
2812 scalar.* = try (try intModScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
39992813 }
4000 return Value.Tag.aggregate.create(allocator, result_data);
2814 return (try mod.intern(.{ .aggregate = .{
2815 .ty = ty.toIntern(),
2816 .storage = .{ .elems = result_data },
2817 } })).toValue();
40012818 }
4002 return intModScalar(lhs, rhs, allocator, target);
2819 return intModScalar(lhs, rhs, ty, allocator, mod);
40032820 }
40042821
4005 pub fn intModScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
2822 pub fn intModScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
40062823 // TODO is this a performance issue? maybe we should try the operation without
40072824 // resorting to BigInt first.
40082825 var lhs_space: Value.BigIntSpace = undefined;
40092826 var rhs_space: Value.BigIntSpace = undefined;
4010 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
4011 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
2827 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
2828 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
40122829 const limbs_q = try allocator.alloc(
40132830 std.math.big.Limb,
40142831 lhs_bigint.limbs.len,
......@@ -4024,161 +2841,164 @@ pub const Value = extern union {
40242841 var result_q = BigIntMutable{ .limbs = limbs_q, .positive = undefined, .len = undefined };
40252842 var result_r = BigIntMutable{ .limbs = limbs_r, .positive = undefined, .len = undefined };
40262843 result_q.divFloor(&result_r, lhs_bigint, rhs_bigint, limbs_buffer);
4027 return fromBigInt(allocator, result_r.toConst());
2844 return mod.intValue_big(ty, result_r.toConst());
40282845 }
40292846
40302847 /// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
4031 pub fn isNan(val: Value) bool {
4032 return switch (val.tag()) {
4033 .float_16 => std.math.isNan(val.castTag(.float_16).?.data),
4034 .float_32 => std.math.isNan(val.castTag(.float_32).?.data),
4035 .float_64 => std.math.isNan(val.castTag(.float_64).?.data),
4036 .float_80 => std.math.isNan(val.castTag(.float_80).?.data),
4037 .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
2848 pub fn isNan(val: Value, mod: *const Module) bool {
2849 if (val.ip_index == .none) return false;
2850 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2851 .float => |float| switch (float.storage) {
2852 inline else => |x| std.math.isNan(x),
2853 },
40382854 else => false,
40392855 };
40402856 }
40412857
40422858 /// Returns true if the value is a floating point type and is infinite. Returns false otherwise.
4043 pub fn isInf(val: Value) bool {
4044 return switch (val.tag()) {
4045 .float_16 => std.math.isInf(val.castTag(.float_16).?.data),
4046 .float_32 => std.math.isInf(val.castTag(.float_32).?.data),
4047 .float_64 => std.math.isInf(val.castTag(.float_64).?.data),
4048 .float_80 => std.math.isInf(val.castTag(.float_80).?.data),
4049 .float_128 => std.math.isInf(val.castTag(.float_128).?.data),
2859 pub fn isInf(val: Value, mod: *const Module) bool {
2860 if (val.ip_index == .none) return false;
2861 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2862 .float => |float| switch (float.storage) {
2863 inline else => |x| std.math.isInf(x),
2864 },
40502865 else => false,
40512866 };
40522867 }
40532868
4054 pub fn isNegativeInf(val: Value) bool {
4055 return switch (val.tag()) {
4056 .float_16 => std.math.isNegativeInf(val.castTag(.float_16).?.data),
4057 .float_32 => std.math.isNegativeInf(val.castTag(.float_32).?.data),
4058 .float_64 => std.math.isNegativeInf(val.castTag(.float_64).?.data),
4059 .float_80 => std.math.isNegativeInf(val.castTag(.float_80).?.data),
4060 .float_128 => std.math.isNegativeInf(val.castTag(.float_128).?.data),
2869 pub fn isNegativeInf(val: Value, mod: *const Module) bool {
2870 if (val.ip_index == .none) return false;
2871 return switch (mod.intern_pool.indexToKey(val.toIntern())) {
2872 .float => |float| switch (float.storage) {
2873 inline else => |x| std.math.isNegativeInf(x),
2874 },
40612875 else => false,
40622876 };
40632877 }
40642878
40652879 pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4066 const target = mod.getTarget();
4067 if (float_type.zigTypeTag() == .Vector) {
4068 const result_data = try arena.alloc(Value, float_type.vectorLen());
2880 if (float_type.zigTypeTag(mod) == .Vector) {
2881 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
2882 const scalar_ty = float_type.scalarType(mod);
40692883 for (result_data, 0..) |*scalar, i| {
4070 var lhs_buf: Value.ElemValueBuffer = undefined;
4071 var rhs_buf: Value.ElemValueBuffer = undefined;
4072 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4073 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4074 scalar.* = try floatRemScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
2884 const lhs_elem = try lhs.elemValue(mod, i);
2885 const rhs_elem = try rhs.elemValue(mod, i);
2886 scalar.* = try (try floatRemScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
40752887 }
4076 return Value.Tag.aggregate.create(arena, result_data);
2888 return (try mod.intern(.{ .aggregate = .{
2889 .ty = float_type.toIntern(),
2890 .storage = .{ .elems = result_data },
2891 } })).toValue();
40772892 }
4078 return floatRemScalar(lhs, rhs, float_type, arena, target);
2893 return floatRemScalar(lhs, rhs, float_type, mod);
40792894 }
40802895
4081 pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
4082 switch (float_type.floatBits(target)) {
4083 16 => {
4084 const lhs_val = lhs.toFloat(f16);
4085 const rhs_val = rhs.toFloat(f16);
4086 return Value.Tag.float_16.create(arena, @rem(lhs_val, rhs_val));
4087 },
4088 32 => {
4089 const lhs_val = lhs.toFloat(f32);
4090 const rhs_val = rhs.toFloat(f32);
4091 return Value.Tag.float_32.create(arena, @rem(lhs_val, rhs_val));
4092 },
4093 64 => {
4094 const lhs_val = lhs.toFloat(f64);
4095 const rhs_val = rhs.toFloat(f64);
4096 return Value.Tag.float_64.create(arena, @rem(lhs_val, rhs_val));
4097 },
4098 80 => {
4099 const lhs_val = lhs.toFloat(f80);
4100 const rhs_val = rhs.toFloat(f80);
4101 return Value.Tag.float_80.create(arena, @rem(lhs_val, rhs_val));
4102 },
4103 128 => {
4104 const lhs_val = lhs.toFloat(f128);
4105 const rhs_val = rhs.toFloat(f128);
4106 return Value.Tag.float_128.create(arena, @rem(lhs_val, rhs_val));
4107 },
2896 pub fn floatRemScalar(lhs: Value, rhs: Value, float_type: Type, mod: *Module) !Value {
2897 const target = mod.getTarget();
2898 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
2899 16 => .{ .f16 = @rem(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
2900 32 => .{ .f32 = @rem(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
2901 64 => .{ .f64 = @rem(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
2902 80 => .{ .f80 = @rem(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
2903 128 => .{ .f128 = @rem(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
41082904 else => unreachable,
4109 }
2905 };
2906 return (try mod.intern(.{ .float = .{
2907 .ty = float_type.toIntern(),
2908 .storage = storage,
2909 } })).toValue();
41102910 }
41112911
41122912 pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4113 const target = mod.getTarget();
4114 if (float_type.zigTypeTag() == .Vector) {
4115 const result_data = try arena.alloc(Value, float_type.vectorLen());
2913 if (float_type.zigTypeTag(mod) == .Vector) {
2914 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
2915 const scalar_ty = float_type.scalarType(mod);
41162916 for (result_data, 0..) |*scalar, i| {
4117 var lhs_buf: Value.ElemValueBuffer = undefined;
4118 var rhs_buf: Value.ElemValueBuffer = undefined;
4119 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4120 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4121 scalar.* = try floatModScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
2917 const lhs_elem = try lhs.elemValue(mod, i);
2918 const rhs_elem = try rhs.elemValue(mod, i);
2919 scalar.* = try (try floatModScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
41222920 }
4123 return Value.Tag.aggregate.create(arena, result_data);
2921 return (try mod.intern(.{ .aggregate = .{
2922 .ty = float_type.toIntern(),
2923 .storage = .{ .elems = result_data },
2924 } })).toValue();
41242925 }
4125 return floatModScalar(lhs, rhs, float_type, arena, target);
2926 return floatModScalar(lhs, rhs, float_type, mod);
41262927 }
41272928
4128 pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, target: Target) !Value {
4129 switch (float_type.floatBits(target)) {
4130 16 => {
4131 const lhs_val = lhs.toFloat(f16);
4132 const rhs_val = rhs.toFloat(f16);
4133 return Value.Tag.float_16.create(arena, @mod(lhs_val, rhs_val));
4134 },
4135 32 => {
4136 const lhs_val = lhs.toFloat(f32);
4137 const rhs_val = rhs.toFloat(f32);
4138 return Value.Tag.float_32.create(arena, @mod(lhs_val, rhs_val));
4139 },
4140 64 => {
4141 const lhs_val = lhs.toFloat(f64);
4142 const rhs_val = rhs.toFloat(f64);
4143 return Value.Tag.float_64.create(arena, @mod(lhs_val, rhs_val));
4144 },
4145 80 => {
4146 const lhs_val = lhs.toFloat(f80);
4147 const rhs_val = rhs.toFloat(f80);
4148 return Value.Tag.float_80.create(arena, @mod(lhs_val, rhs_val));
4149 },
4150 128 => {
4151 const lhs_val = lhs.toFloat(f128);
4152 const rhs_val = rhs.toFloat(f128);
4153 return Value.Tag.float_128.create(arena, @mod(lhs_val, rhs_val));
4154 },
2929 pub fn floatModScalar(lhs: Value, rhs: Value, float_type: Type, mod: *Module) !Value {
2930 const target = mod.getTarget();
2931 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
2932 16 => .{ .f16 = @mod(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
2933 32 => .{ .f32 = @mod(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
2934 64 => .{ .f64 = @mod(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
2935 80 => .{ .f80 = @mod(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
2936 128 => .{ .f128 = @mod(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
41552937 else => unreachable,
4156 }
2938 };
2939 return (try mod.intern(.{ .float = .{
2940 .ty = float_type.toIntern(),
2941 .storage = storage,
2942 } })).toValue();
2943 }
2944
2945 /// If the value overflowed the type, returns a comptime_int (or vector thereof) instead, setting
2946 /// overflow_idx to the vector index the overflow was at (or 0 for a scalar).
2947 pub fn intMul(lhs: Value, rhs: Value, ty: Type, overflow_idx: *?usize, allocator: Allocator, mod: *Module) !Value {
2948 var overflow: usize = undefined;
2949 return intMulInner(lhs, rhs, ty, &overflow, allocator, mod) catch |err| switch (err) {
2950 error.Overflow => {
2951 const is_vec = ty.isVector(mod);
2952 overflow_idx.* = if (is_vec) overflow else 0;
2953 const safe_ty = if (is_vec) try mod.vectorType(.{
2954 .len = ty.vectorLen(mod),
2955 .child = .comptime_int_type,
2956 }) else Type.comptime_int;
2957 return intMulInner(lhs, rhs, safe_ty, undefined, allocator, mod) catch |err1| switch (err1) {
2958 error.Overflow => unreachable,
2959 else => |e| return e,
2960 };
2961 },
2962 else => |e| return e,
2963 };
41572964 }
41582965
4159 pub fn intMul(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
4160 const target = mod.getTarget();
4161 if (ty.zigTypeTag() == .Vector) {
4162 const result_data = try allocator.alloc(Value, ty.vectorLen());
2966 fn intMulInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator: Allocator, mod: *Module) !Value {
2967 if (ty.zigTypeTag(mod) == .Vector) {
2968 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
2969 const scalar_ty = ty.scalarType(mod);
41632970 for (result_data, 0..) |*scalar, i| {
4164 var lhs_buf: Value.ElemValueBuffer = undefined;
4165 var rhs_buf: Value.ElemValueBuffer = undefined;
4166 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4167 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4168 scalar.* = try intMulScalar(lhs_elem, rhs_elem, allocator, target);
2971 const lhs_elem = try lhs.elemValue(mod, i);
2972 const rhs_elem = try rhs.elemValue(mod, i);
2973 const val = intMulScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod) catch |err| switch (err) {
2974 error.Overflow => {
2975 overflow_idx.* = i;
2976 return error.Overflow;
2977 },
2978 else => |e| return e,
2979 };
2980 scalar.* = try val.intern(scalar_ty, mod);
41692981 }
4170 return Value.Tag.aggregate.create(allocator, result_data);
2982 return (try mod.intern(.{ .aggregate = .{
2983 .ty = ty.toIntern(),
2984 .storage = .{ .elems = result_data },
2985 } })).toValue();
41712986 }
4172 return intMulScalar(lhs, rhs, allocator, target);
2987 return intMulScalar(lhs, rhs, ty, allocator, mod);
41732988 }
41742989
4175 pub fn intMulScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
2990 pub fn intMulScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
2991 if (ty.toIntern() != .comptime_int_type) {
2992 const res = try intMulWithOverflowScalar(lhs, rhs, ty, allocator, mod);
2993 if (res.overflow_bit.compareAllWithZero(.neq, mod)) return error.Overflow;
2994 return res.wrapped_result;
2995 }
41762996 // TODO is this a performance issue? maybe we should try the operation without
41772997 // resorting to BigInt first.
41782998 var lhs_space: Value.BigIntSpace = undefined;
41792999 var rhs_space: Value.BigIntSpace = undefined;
4180 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
4181 const rhs_bigint = rhs.toBigInt(&rhs_space, target);
3000 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3001 const rhs_bigint = rhs.toBigInt(&rhs_space, mod);
41823002 const limbs = try allocator.alloc(
41833003 std.math.big.Limb,
41843004 lhs_bigint.limbs.len + rhs_bigint.limbs.len,
......@@ -4190,21 +3010,23 @@ pub const Value = extern union {
41903010 );
41913011 defer allocator.free(limbs_buffer);
41923012 result_bigint.mul(lhs_bigint, rhs_bigint, limbs_buffer, allocator);
4193 return fromBigInt(allocator, result_bigint.toConst());
3013 return mod.intValue_big(ty, result_bigint.toConst());
41943014 }
41953015
41963016 pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, mod: *Module) !Value {
4197 const target = mod.getTarget();
4198 if (ty.zigTypeTag() == .Vector) {
4199 const result_data = try allocator.alloc(Value, ty.vectorLen());
3017 if (ty.zigTypeTag(mod) == .Vector) {
3018 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3019 const scalar_ty = ty.scalarType(mod);
42003020 for (result_data, 0..) |*scalar, i| {
4201 var buf: Value.ElemValueBuffer = undefined;
4202 const elem_val = val.elemValueBuffer(mod, i, &buf);
4203 scalar.* = try intTruncScalar(elem_val, allocator, signedness, bits, target);
3021 const elem_val = try val.elemValue(mod, i);
3022 scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, bits, mod)).intern(scalar_ty, mod);
42043023 }
4205 return Value.Tag.aggregate.create(allocator, result_data);
3024 return (try mod.intern(.{ .aggregate = .{
3025 .ty = ty.toIntern(),
3026 .storage = .{ .elems = result_data },
3027 } })).toValue();
42063028 }
4207 return intTruncScalar(val, allocator, signedness, bits, target);
3029 return intTruncScalar(val, ty, allocator, signedness, bits, mod);
42083030 }
42093031
42103032 /// This variant may vectorize on `bits`. Asserts that `bits` is a (vector of) `u16`.
......@@ -4216,26 +3038,34 @@ pub const Value = extern union {
42163038 bits: Value,
42173039 mod: *Module,
42183040 ) !Value {
4219 const target = mod.getTarget();
4220 if (ty.zigTypeTag() == .Vector) {
4221 const result_data = try allocator.alloc(Value, ty.vectorLen());
3041 if (ty.zigTypeTag(mod) == .Vector) {
3042 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3043 const scalar_ty = ty.scalarType(mod);
42223044 for (result_data, 0..) |*scalar, i| {
4223 var buf: Value.ElemValueBuffer = undefined;
4224 const elem_val = val.elemValueBuffer(mod, i, &buf);
4225 var bits_buf: Value.ElemValueBuffer = undefined;
4226 const bits_elem = bits.elemValueBuffer(mod, i, &bits_buf);
4227 scalar.* = try intTruncScalar(elem_val, allocator, signedness, @intCast(u16, bits_elem.toUnsignedInt(target)), target);
3045 const elem_val = try val.elemValue(mod, i);
3046 const bits_elem = try bits.elemValue(mod, i);
3047 scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @intCast(u16, bits_elem.toUnsignedInt(mod)), mod)).intern(scalar_ty, mod);
42283048 }
4229 return Value.Tag.aggregate.create(allocator, result_data);
3049 return (try mod.intern(.{ .aggregate = .{
3050 .ty = ty.toIntern(),
3051 .storage = .{ .elems = result_data },
3052 } })).toValue();
42303053 }
4231 return intTruncScalar(val, allocator, signedness, @intCast(u16, bits.toUnsignedInt(target)), target);
3054 return intTruncScalar(val, ty, allocator, signedness, @intCast(u16, bits.toUnsignedInt(mod)), mod);
42323055 }
42333056
4234 pub fn intTruncScalar(val: Value, allocator: Allocator, signedness: std.builtin.Signedness, bits: u16, target: Target) !Value {
4235 if (bits == 0) return Value.zero;
3057 pub fn intTruncScalar(
3058 val: Value,
3059 ty: Type,
3060 allocator: Allocator,
3061 signedness: std.builtin.Signedness,
3062 bits: u16,
3063 mod: *Module,
3064 ) !Value {
3065 if (bits == 0) return mod.intValue(ty, 0);
42363066
42373067 var val_space: Value.BigIntSpace = undefined;
4238 const val_bigint = val.toBigInt(&val_space, target);
3068 const val_bigint = val.toBigInt(&val_space, mod);
42393069
42403070 const limbs = try allocator.alloc(
42413071 std.math.big.Limb,
......@@ -4244,31 +3074,32 @@ pub const Value = extern union {
42443074 var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
42453075
42463076 result_bigint.truncate(val_bigint, signedness, bits);
4247 return fromBigInt(allocator, result_bigint.toConst());
3077 return mod.intValue_big(ty, result_bigint.toConst());
42483078 }
42493079
42503080 pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
4251 const target = mod.getTarget();
4252 if (ty.zigTypeTag() == .Vector) {
4253 const result_data = try allocator.alloc(Value, ty.vectorLen());
3081 if (ty.zigTypeTag(mod) == .Vector) {
3082 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3083 const scalar_ty = ty.scalarType(mod);
42543084 for (result_data, 0..) |*scalar, i| {
4255 var lhs_buf: Value.ElemValueBuffer = undefined;
4256 var rhs_buf: Value.ElemValueBuffer = undefined;
4257 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4258 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4259 scalar.* = try shlScalar(lhs_elem, rhs_elem, allocator, target);
3085 const lhs_elem = try lhs.elemValue(mod, i);
3086 const rhs_elem = try rhs.elemValue(mod, i);
3087 scalar.* = try (try shlScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
42603088 }
4261 return Value.Tag.aggregate.create(allocator, result_data);
3089 return (try mod.intern(.{ .aggregate = .{
3090 .ty = ty.toIntern(),
3091 .storage = .{ .elems = result_data },
3092 } })).toValue();
42623093 }
4263 return shlScalar(lhs, rhs, allocator, target);
3094 return shlScalar(lhs, rhs, ty, allocator, mod);
42643095 }
42653096
4266 pub fn shlScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
3097 pub fn shlScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
42673098 // TODO is this a performance issue? maybe we should try the operation without
42683099 // resorting to BigInt first.
42693100 var lhs_space: Value.BigIntSpace = undefined;
4270 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
4271 const shift = @intCast(usize, rhs.toUnsignedInt(target));
3101 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3102 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
42723103 const limbs = try allocator.alloc(
42733104 std.math.big.Limb,
42743105 lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,
......@@ -4279,7 +3110,12 @@ pub const Value = extern union {
42793110 .len = undefined,
42803111 };
42813112 result_bigint.shiftLeft(lhs_bigint, shift);
4282 return fromBigInt(allocator, result_bigint.toConst());
3113 if (ty.toIntern() != .comptime_int_type) {
3114 const int_info = ty.intInfo(mod);
3115 result_bigint.truncate(result_bigint.toConst(), int_info.signedness, int_info.bits);
3116 }
3117
3118 return mod.intValue_big(ty, result_bigint.toConst());
42833119 }
42843120
42853121 pub fn shlWithOverflow(
......@@ -4289,25 +3125,30 @@ pub const Value = extern union {
42893125 allocator: Allocator,
42903126 mod: *Module,
42913127 ) !OverflowArithmeticResult {
4292 const target = mod.getTarget();
4293 if (ty.zigTypeTag() == .Vector) {
4294 const overflowed_data = try allocator.alloc(Value, ty.vectorLen());
4295 const result_data = try allocator.alloc(Value, ty.vectorLen());
4296 for (result_data, 0..) |*scalar, i| {
4297 var lhs_buf: Value.ElemValueBuffer = undefined;
4298 var rhs_buf: Value.ElemValueBuffer = undefined;
4299 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4300 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4301 const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), allocator, target);
4302 overflowed_data[i] = of_math_result.overflow_bit;
4303 scalar.* = of_math_result.wrapped_result;
3128 if (ty.zigTypeTag(mod) == .Vector) {
3129 const vec_len = ty.vectorLen(mod);
3130 const overflowed_data = try allocator.alloc(InternPool.Index, vec_len);
3131 const result_data = try allocator.alloc(InternPool.Index, vec_len);
3132 const scalar_ty = ty.scalarType(mod);
3133 for (overflowed_data, result_data, 0..) |*of, *scalar, i| {
3134 const lhs_elem = try lhs.elemValue(mod, i);
3135 const rhs_elem = try rhs.elemValue(mod, i);
3136 const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod);
3137 of.* = try of_math_result.overflow_bit.intern(Type.u1, mod);
3138 scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod);
43043139 }
43053140 return OverflowArithmeticResult{
4306 .overflow_bit = try Value.Tag.aggregate.create(allocator, overflowed_data),
4307 .wrapped_result = try Value.Tag.aggregate.create(allocator, result_data),
3141 .overflow_bit = (try mod.intern(.{ .aggregate = .{
3142 .ty = (try mod.vectorType(.{ .len = vec_len, .child = .u1_type })).toIntern(),
3143 .storage = .{ .elems = overflowed_data },
3144 } })).toValue(),
3145 .wrapped_result = (try mod.intern(.{ .aggregate = .{
3146 .ty = ty.toIntern(),
3147 .storage = .{ .elems = result_data },
3148 } })).toValue(),
43083149 };
43093150 }
4310 return shlWithOverflowScalar(lhs, rhs, ty, allocator, target);
3151 return shlWithOverflowScalar(lhs, rhs, ty, allocator, mod);
43113152 }
43123153
43133154 pub fn shlWithOverflowScalar(
......@@ -4315,12 +3156,12 @@ pub const Value = extern union {
43153156 rhs: Value,
43163157 ty: Type,
43173158 allocator: Allocator,
4318 target: Target,
3159 mod: *Module,
43193160 ) !OverflowArithmeticResult {
4320 const info = ty.intInfo(target);
3161 const info = ty.intInfo(mod);
43213162 var lhs_space: Value.BigIntSpace = undefined;
4322 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
4323 const shift = @intCast(usize, rhs.toUnsignedInt(target));
3163 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3164 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
43243165 const limbs = try allocator.alloc(
43253166 std.math.big.Limb,
43263167 lhs_bigint.limbs.len + (shift / (@sizeOf(std.math.big.Limb) * 8)) + 1,
......@@ -4336,8 +3177,8 @@ pub const Value = extern union {
43363177 result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);
43373178 }
43383179 return OverflowArithmeticResult{
4339 .overflow_bit = boolToInt(overflowed),
4340 .wrapped_result = try fromBigInt(allocator, result_bigint.toConst()),
3180 .overflow_bit = try mod.intValue(Type.u1, @boolToInt(overflowed)),
3181 .wrapped_result = try mod.intValue_big(ty, result_bigint.toConst()),
43413182 };
43423183 }
43433184
......@@ -4348,19 +3189,20 @@ pub const Value = extern union {
43483189 arena: Allocator,
43493190 mod: *Module,
43503191 ) !Value {
4351 const target = mod.getTarget();
4352 if (ty.zigTypeTag() == .Vector) {
4353 const result_data = try arena.alloc(Value, ty.vectorLen());
3192 if (ty.zigTypeTag(mod) == .Vector) {
3193 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3194 const scalar_ty = ty.scalarType(mod);
43543195 for (result_data, 0..) |*scalar, i| {
4355 var lhs_buf: Value.ElemValueBuffer = undefined;
4356 var rhs_buf: Value.ElemValueBuffer = undefined;
4357 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4358 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4359 scalar.* = try shlSatScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
3196 const lhs_elem = try lhs.elemValue(mod, i);
3197 const rhs_elem = try rhs.elemValue(mod, i);
3198 scalar.* = try (try shlSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
43603199 }
4361 return Value.Tag.aggregate.create(arena, result_data);
3200 return (try mod.intern(.{ .aggregate = .{
3201 .ty = ty.toIntern(),
3202 .storage = .{ .elems = result_data },
3203 } })).toValue();
43623204 }
4363 return shlSatScalar(lhs, rhs, ty, arena, target);
3205 return shlSatScalar(lhs, rhs, ty, arena, mod);
43643206 }
43653207
43663208 pub fn shlSatScalar(
......@@ -4368,15 +3210,15 @@ pub const Value = extern union {
43683210 rhs: Value,
43693211 ty: Type,
43703212 arena: Allocator,
4371 target: Target,
3213 mod: *Module,
43723214 ) !Value {
43733215 // TODO is this a performance issue? maybe we should try the operation without
43743216 // resorting to BigInt first.
4375 const info = ty.intInfo(target);
3217 const info = ty.intInfo(mod);
43763218
43773219 var lhs_space: Value.BigIntSpace = undefined;
4378 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
4379 const shift = @intCast(usize, rhs.toUnsignedInt(target));
3220 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3221 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
43803222 const limbs = try arena.alloc(
43813223 std.math.big.Limb,
43823224 std.math.big.int.calcTwosCompLimbCount(info.bits) + 1,
......@@ -4387,7 +3229,7 @@ pub const Value = extern union {
43873229 .len = undefined,
43883230 };
43893231 result_bigint.shiftLeftSat(lhs_bigint, shift, info.signedness, info.bits);
4390 return fromBigInt(arena, result_bigint.toConst());
3232 return mod.intValue_big(ty, result_bigint.toConst());
43913233 }
43923234
43933235 pub fn shlTrunc(
......@@ -4397,16 +3239,18 @@ pub const Value = extern union {
43973239 arena: Allocator,
43983240 mod: *Module,
43993241 ) !Value {
4400 if (ty.zigTypeTag() == .Vector) {
4401 const result_data = try arena.alloc(Value, ty.vectorLen());
3242 if (ty.zigTypeTag(mod) == .Vector) {
3243 const result_data = try arena.alloc(InternPool.Index, ty.vectorLen(mod));
3244 const scalar_ty = ty.scalarType(mod);
44023245 for (result_data, 0..) |*scalar, i| {
4403 var lhs_buf: Value.ElemValueBuffer = undefined;
4404 var rhs_buf: Value.ElemValueBuffer = undefined;
4405 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4406 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4407 scalar.* = try shlTruncScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, mod);
3246 const lhs_elem = try lhs.elemValue(mod, i);
3247 const rhs_elem = try rhs.elemValue(mod, i);
3248 scalar.* = try (try shlTruncScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod);
44083249 }
4409 return Value.Tag.aggregate.create(arena, result_data);
3250 return (try mod.intern(.{ .aggregate = .{
3251 .ty = ty.toIntern(),
3252 .storage = .{ .elems = result_data },
3253 } })).toValue();
44103254 }
44113255 return shlTruncScalar(lhs, rhs, ty, arena, mod);
44123256 }
......@@ -4419,42 +3263,43 @@ pub const Value = extern union {
44193263 mod: *Module,
44203264 ) !Value {
44213265 const shifted = try lhs.shl(rhs, ty, arena, mod);
4422 const int_info = ty.intInfo(mod.getTarget());
3266 const int_info = ty.intInfo(mod);
44233267 const truncated = try shifted.intTrunc(ty, arena, int_info.signedness, int_info.bits, mod);
44243268 return truncated;
44253269 }
44263270
44273271 pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
4428 const target = mod.getTarget();
4429 if (ty.zigTypeTag() == .Vector) {
4430 const result_data = try allocator.alloc(Value, ty.vectorLen());
3272 if (ty.zigTypeTag(mod) == .Vector) {
3273 const result_data = try allocator.alloc(InternPool.Index, ty.vectorLen(mod));
3274 const scalar_ty = ty.scalarType(mod);
44313275 for (result_data, 0..) |*scalar, i| {
4432 var lhs_buf: Value.ElemValueBuffer = undefined;
4433 var rhs_buf: Value.ElemValueBuffer = undefined;
4434 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4435 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4436 scalar.* = try shrScalar(lhs_elem, rhs_elem, allocator, target);
3276 const lhs_elem = try lhs.elemValue(mod, i);
3277 const rhs_elem = try rhs.elemValue(mod, i);
3278 scalar.* = try (try shrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod);
44373279 }
4438 return Value.Tag.aggregate.create(allocator, result_data);
3280 return (try mod.intern(.{ .aggregate = .{
3281 .ty = ty.toIntern(),
3282 .storage = .{ .elems = result_data },
3283 } })).toValue();
44393284 }
4440 return shrScalar(lhs, rhs, allocator, target);
3285 return shrScalar(lhs, rhs, ty, allocator, mod);
44413286 }
44423287
4443 pub fn shrScalar(lhs: Value, rhs: Value, allocator: Allocator, target: Target) !Value {
3288 pub fn shrScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) !Value {
44443289 // TODO is this a performance issue? maybe we should try the operation without
44453290 // resorting to BigInt first.
44463291 var lhs_space: Value.BigIntSpace = undefined;
4447 const lhs_bigint = lhs.toBigInt(&lhs_space, target);
4448 const shift = @intCast(usize, rhs.toUnsignedInt(target));
3292 const lhs_bigint = lhs.toBigInt(&lhs_space, mod);
3293 const shift = @intCast(usize, rhs.toUnsignedInt(mod));
44493294
44503295 const result_limbs = lhs_bigint.limbs.len -| (shift / (@sizeOf(std.math.big.Limb) * 8));
44513296 if (result_limbs == 0) {
44523297 // The shift is enough to remove all the bits from the number, which means the
44533298 // result is 0 or -1 depending on the sign.
44543299 if (lhs_bigint.positive) {
4455 return Value.zero;
3300 return mod.intValue(ty, 0);
44563301 } else {
4457 return Value.negative_one;
3302 return mod.intValue(ty, -1);
44583303 }
44593304 }
44603305
......@@ -4468,7 +3313,7 @@ pub const Value = extern union {
44683313 .len = undefined,
44693314 };
44703315 result_bigint.shiftRight(lhs_bigint, shift);
4471 return fromBigInt(allocator, result_bigint.toConst());
3316 return mod.intValue_big(ty, result_bigint.toConst());
44723317 }
44733318
44743319 pub fn floatNeg(
......@@ -4477,33 +3322,127 @@ pub const Value = extern union {
44773322 arena: Allocator,
44783323 mod: *Module,
44793324 ) !Value {
4480 const target = mod.getTarget();
4481 if (float_type.zigTypeTag() == .Vector) {
4482 const result_data = try arena.alloc(Value, float_type.vectorLen());
3325 if (float_type.zigTypeTag(mod) == .Vector) {
3326 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3327 const scalar_ty = float_type.scalarType(mod);
44833328 for (result_data, 0..) |*scalar, i| {
4484 var buf: Value.ElemValueBuffer = undefined;
4485 const elem_val = val.elemValueBuffer(mod, i, &buf);
4486 scalar.* = try floatNegScalar(elem_val, float_type.scalarType(), arena, target);
3329 const elem_val = try val.elemValue(mod, i);
3330 scalar.* = try (try floatNegScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
44873331 }
4488 return Value.Tag.aggregate.create(arena, result_data);
3332 return (try mod.intern(.{ .aggregate = .{
3333 .ty = float_type.toIntern(),
3334 .storage = .{ .elems = result_data },
3335 } })).toValue();
44893336 }
4490 return floatNegScalar(val, float_type, arena, target);
3337 return floatNegScalar(val, float_type, mod);
44913338 }
44923339
44933340 pub fn floatNegScalar(
44943341 val: Value,
44953342 float_type: Type,
3343 mod: *Module,
3344 ) !Value {
3345 const target = mod.getTarget();
3346 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3347 16 => .{ .f16 = -val.toFloat(f16, mod) },
3348 32 => .{ .f32 = -val.toFloat(f32, mod) },
3349 64 => .{ .f64 = -val.toFloat(f64, mod) },
3350 80 => .{ .f80 = -val.toFloat(f80, mod) },
3351 128 => .{ .f128 = -val.toFloat(f128, mod) },
3352 else => unreachable,
3353 };
3354 return (try mod.intern(.{ .float = .{
3355 .ty = float_type.toIntern(),
3356 .storage = storage,
3357 } })).toValue();
3358 }
3359
3360 pub fn floatAdd(
3361 lhs: Value,
3362 rhs: Value,
3363 float_type: Type,
44963364 arena: Allocator,
4497 target: Target,
3365 mod: *Module,
3366 ) !Value {
3367 if (float_type.zigTypeTag(mod) == .Vector) {
3368 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3369 const scalar_ty = float_type.scalarType(mod);
3370 for (result_data, 0..) |*scalar, i| {
3371 const lhs_elem = try lhs.elemValue(mod, i);
3372 const rhs_elem = try rhs.elemValue(mod, i);
3373 scalar.* = try (try floatAddScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
3374 }
3375 return (try mod.intern(.{ .aggregate = .{
3376 .ty = float_type.toIntern(),
3377 .storage = .{ .elems = result_data },
3378 } })).toValue();
3379 }
3380 return floatAddScalar(lhs, rhs, float_type, mod);
3381 }
3382
3383 pub fn floatAddScalar(
3384 lhs: Value,
3385 rhs: Value,
3386 float_type: Type,
3387 mod: *Module,
44983388 ) !Value {
4499 switch (float_type.floatBits(target)) {
4500 16 => return Value.Tag.float_16.create(arena, -val.toFloat(f16)),
4501 32 => return Value.Tag.float_32.create(arena, -val.toFloat(f32)),
4502 64 => return Value.Tag.float_64.create(arena, -val.toFloat(f64)),
4503 80 => return Value.Tag.float_80.create(arena, -val.toFloat(f80)),
4504 128 => return Value.Tag.float_128.create(arena, -val.toFloat(f128)),
3389 const target = mod.getTarget();
3390 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3391 16 => .{ .f16 = lhs.toFloat(f16, mod) + rhs.toFloat(f16, mod) },
3392 32 => .{ .f32 = lhs.toFloat(f32, mod) + rhs.toFloat(f32, mod) },
3393 64 => .{ .f64 = lhs.toFloat(f64, mod) + rhs.toFloat(f64, mod) },
3394 80 => .{ .f80 = lhs.toFloat(f80, mod) + rhs.toFloat(f80, mod) },
3395 128 => .{ .f128 = lhs.toFloat(f128, mod) + rhs.toFloat(f128, mod) },
45053396 else => unreachable,
3397 };
3398 return (try mod.intern(.{ .float = .{
3399 .ty = float_type.toIntern(),
3400 .storage = storage,
3401 } })).toValue();
3402 }
3403
3404 pub fn floatSub(
3405 lhs: Value,
3406 rhs: Value,
3407 float_type: Type,
3408 arena: Allocator,
3409 mod: *Module,
3410 ) !Value {
3411 if (float_type.zigTypeTag(mod) == .Vector) {
3412 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3413 const scalar_ty = float_type.scalarType(mod);
3414 for (result_data, 0..) |*scalar, i| {
3415 const lhs_elem = try lhs.elemValue(mod, i);
3416 const rhs_elem = try rhs.elemValue(mod, i);
3417 scalar.* = try (try floatSubScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
3418 }
3419 return (try mod.intern(.{ .aggregate = .{
3420 .ty = float_type.toIntern(),
3421 .storage = .{ .elems = result_data },
3422 } })).toValue();
45063423 }
3424 return floatSubScalar(lhs, rhs, float_type, mod);
3425 }
3426
3427 pub fn floatSubScalar(
3428 lhs: Value,
3429 rhs: Value,
3430 float_type: Type,
3431 mod: *Module,
3432 ) !Value {
3433 const target = mod.getTarget();
3434 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3435 16 => .{ .f16 = lhs.toFloat(f16, mod) - rhs.toFloat(f16, mod) },
3436 32 => .{ .f32 = lhs.toFloat(f32, mod) - rhs.toFloat(f32, mod) },
3437 64 => .{ .f64 = lhs.toFloat(f64, mod) - rhs.toFloat(f64, mod) },
3438 80 => .{ .f80 = lhs.toFloat(f80, mod) - rhs.toFloat(f80, mod) },
3439 128 => .{ .f128 = lhs.toFloat(f128, mod) - rhs.toFloat(f128, mod) },
3440 else => unreachable,
3441 };
3442 return (try mod.intern(.{ .float = .{
3443 .ty = float_type.toIntern(),
3444 .storage = storage,
3445 } })).toValue();
45073446 }
45083447
45093448 pub fn floatDiv(
......@@ -4513,56 +3452,41 @@ pub const Value = extern union {
45133452 arena: Allocator,
45143453 mod: *Module,
45153454 ) !Value {
4516 const target = mod.getTarget();
4517 if (float_type.zigTypeTag() == .Vector) {
4518 const result_data = try arena.alloc(Value, float_type.vectorLen());
3455 if (float_type.zigTypeTag(mod) == .Vector) {
3456 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3457 const scalar_ty = float_type.scalarType(mod);
45193458 for (result_data, 0..) |*scalar, i| {
4520 var lhs_buf: Value.ElemValueBuffer = undefined;
4521 var rhs_buf: Value.ElemValueBuffer = undefined;
4522 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4523 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4524 scalar.* = try floatDivScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
3459 const lhs_elem = try lhs.elemValue(mod, i);
3460 const rhs_elem = try rhs.elemValue(mod, i);
3461 scalar.* = try (try floatDivScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
45253462 }
4526 return Value.Tag.aggregate.create(arena, result_data);
3463 return (try mod.intern(.{ .aggregate = .{
3464 .ty = float_type.toIntern(),
3465 .storage = .{ .elems = result_data },
3466 } })).toValue();
45273467 }
4528 return floatDivScalar(lhs, rhs, float_type, arena, target);
3468 return floatDivScalar(lhs, rhs, float_type, mod);
45293469 }
45303470
45313471 pub fn floatDivScalar(
45323472 lhs: Value,
45333473 rhs: Value,
45343474 float_type: Type,
4535 arena: Allocator,
4536 target: Target,
3475 mod: *Module,
45373476 ) !Value {
4538 switch (float_type.floatBits(target)) {
4539 16 => {
4540 const lhs_val = lhs.toFloat(f16);
4541 const rhs_val = rhs.toFloat(f16);
4542 return Value.Tag.float_16.create(arena, lhs_val / rhs_val);
4543 },
4544 32 => {
4545 const lhs_val = lhs.toFloat(f32);
4546 const rhs_val = rhs.toFloat(f32);
4547 return Value.Tag.float_32.create(arena, lhs_val / rhs_val);
4548 },
4549 64 => {
4550 const lhs_val = lhs.toFloat(f64);
4551 const rhs_val = rhs.toFloat(f64);
4552 return Value.Tag.float_64.create(arena, lhs_val / rhs_val);
4553 },
4554 80 => {
4555 const lhs_val = lhs.toFloat(f80);
4556 const rhs_val = rhs.toFloat(f80);
4557 return Value.Tag.float_80.create(arena, lhs_val / rhs_val);
4558 },
4559 128 => {
4560 const lhs_val = lhs.toFloat(f128);
4561 const rhs_val = rhs.toFloat(f128);
4562 return Value.Tag.float_128.create(arena, lhs_val / rhs_val);
4563 },
3477 const target = mod.getTarget();
3478 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3479 16 => .{ .f16 = lhs.toFloat(f16, mod) / rhs.toFloat(f16, mod) },
3480 32 => .{ .f32 = lhs.toFloat(f32, mod) / rhs.toFloat(f32, mod) },
3481 64 => .{ .f64 = lhs.toFloat(f64, mod) / rhs.toFloat(f64, mod) },
3482 80 => .{ .f80 = lhs.toFloat(f80, mod) / rhs.toFloat(f80, mod) },
3483 128 => .{ .f128 = lhs.toFloat(f128, mod) / rhs.toFloat(f128, mod) },
45643484 else => unreachable,
4565 }
3485 };
3486 return (try mod.intern(.{ .float = .{
3487 .ty = float_type.toIntern(),
3488 .storage = storage,
3489 } })).toValue();
45663490 }
45673491
45683492 pub fn floatDivFloor(
......@@ -4572,56 +3496,41 @@ pub const Value = extern union {
45723496 arena: Allocator,
45733497 mod: *Module,
45743498 ) !Value {
4575 const target = mod.getTarget();
4576 if (float_type.zigTypeTag() == .Vector) {
4577 const result_data = try arena.alloc(Value, float_type.vectorLen());
3499 if (float_type.zigTypeTag(mod) == .Vector) {
3500 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3501 const scalar_ty = float_type.scalarType(mod);
45783502 for (result_data, 0..) |*scalar, i| {
4579 var lhs_buf: Value.ElemValueBuffer = undefined;
4580 var rhs_buf: Value.ElemValueBuffer = undefined;
4581 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4582 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4583 scalar.* = try floatDivFloorScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
3503 const lhs_elem = try lhs.elemValue(mod, i);
3504 const rhs_elem = try rhs.elemValue(mod, i);
3505 scalar.* = try (try floatDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
45843506 }
4585 return Value.Tag.aggregate.create(arena, result_data);
3507 return (try mod.intern(.{ .aggregate = .{
3508 .ty = float_type.toIntern(),
3509 .storage = .{ .elems = result_data },
3510 } })).toValue();
45863511 }
4587 return floatDivFloorScalar(lhs, rhs, float_type, arena, target);
3512 return floatDivFloorScalar(lhs, rhs, float_type, mod);
45883513 }
45893514
45903515 pub fn floatDivFloorScalar(
45913516 lhs: Value,
45923517 rhs: Value,
45933518 float_type: Type,
4594 arena: Allocator,
4595 target: Target,
3519 mod: *Module,
45963520 ) !Value {
4597 switch (float_type.floatBits(target)) {
4598 16 => {
4599 const lhs_val = lhs.toFloat(f16);
4600 const rhs_val = rhs.toFloat(f16);
4601 return Value.Tag.float_16.create(arena, @divFloor(lhs_val, rhs_val));
4602 },
4603 32 => {
4604 const lhs_val = lhs.toFloat(f32);
4605 const rhs_val = rhs.toFloat(f32);
4606 return Value.Tag.float_32.create(arena, @divFloor(lhs_val, rhs_val));
4607 },
4608 64 => {
4609 const lhs_val = lhs.toFloat(f64);
4610 const rhs_val = rhs.toFloat(f64);
4611 return Value.Tag.float_64.create(arena, @divFloor(lhs_val, rhs_val));
4612 },
4613 80 => {
4614 const lhs_val = lhs.toFloat(f80);
4615 const rhs_val = rhs.toFloat(f80);
4616 return Value.Tag.float_80.create(arena, @divFloor(lhs_val, rhs_val));
4617 },
4618 128 => {
4619 const lhs_val = lhs.toFloat(f128);
4620 const rhs_val = rhs.toFloat(f128);
4621 return Value.Tag.float_128.create(arena, @divFloor(lhs_val, rhs_val));
4622 },
3521 const target = mod.getTarget();
3522 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3523 16 => .{ .f16 = @divFloor(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
3524 32 => .{ .f32 = @divFloor(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
3525 64 => .{ .f64 = @divFloor(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
3526 80 => .{ .f80 = @divFloor(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
3527 128 => .{ .f128 = @divFloor(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
46233528 else => unreachable,
4624 }
3529 };
3530 return (try mod.intern(.{ .float = .{
3531 .ty = float_type.toIntern(),
3532 .storage = storage,
3533 } })).toValue();
46253534 }
46263535
46273536 pub fn floatDivTrunc(
......@@ -4631,56 +3540,41 @@ pub const Value = extern union {
46313540 arena: Allocator,
46323541 mod: *Module,
46333542 ) !Value {
4634 const target = mod.getTarget();
4635 if (float_type.zigTypeTag() == .Vector) {
4636 const result_data = try arena.alloc(Value, float_type.vectorLen());
3543 if (float_type.zigTypeTag(mod) == .Vector) {
3544 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3545 const scalar_ty = float_type.scalarType(mod);
46373546 for (result_data, 0..) |*scalar, i| {
4638 var lhs_buf: Value.ElemValueBuffer = undefined;
4639 var rhs_buf: Value.ElemValueBuffer = undefined;
4640 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4641 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4642 scalar.* = try floatDivTruncScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
3547 const lhs_elem = try lhs.elemValue(mod, i);
3548 const rhs_elem = try rhs.elemValue(mod, i);
3549 scalar.* = try (try floatDivTruncScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
46433550 }
4644 return Value.Tag.aggregate.create(arena, result_data);
3551 return (try mod.intern(.{ .aggregate = .{
3552 .ty = float_type.toIntern(),
3553 .storage = .{ .elems = result_data },
3554 } })).toValue();
46453555 }
4646 return floatDivTruncScalar(lhs, rhs, float_type, arena, target);
3556 return floatDivTruncScalar(lhs, rhs, float_type, mod);
46473557 }
46483558
46493559 pub fn floatDivTruncScalar(
46503560 lhs: Value,
46513561 rhs: Value,
46523562 float_type: Type,
4653 arena: Allocator,
4654 target: Target,
3563 mod: *Module,
46553564 ) !Value {
4656 switch (float_type.floatBits(target)) {
4657 16 => {
4658 const lhs_val = lhs.toFloat(f16);
4659 const rhs_val = rhs.toFloat(f16);
4660 return Value.Tag.float_16.create(arena, @divTrunc(lhs_val, rhs_val));
4661 },
4662 32 => {
4663 const lhs_val = lhs.toFloat(f32);
4664 const rhs_val = rhs.toFloat(f32);
4665 return Value.Tag.float_32.create(arena, @divTrunc(lhs_val, rhs_val));
4666 },
4667 64 => {
4668 const lhs_val = lhs.toFloat(f64);
4669 const rhs_val = rhs.toFloat(f64);
4670 return Value.Tag.float_64.create(arena, @divTrunc(lhs_val, rhs_val));
4671 },
4672 80 => {
4673 const lhs_val = lhs.toFloat(f80);
4674 const rhs_val = rhs.toFloat(f80);
4675 return Value.Tag.float_80.create(arena, @divTrunc(lhs_val, rhs_val));
4676 },
4677 128 => {
4678 const lhs_val = lhs.toFloat(f128);
4679 const rhs_val = rhs.toFloat(f128);
4680 return Value.Tag.float_128.create(arena, @divTrunc(lhs_val, rhs_val));
4681 },
3565 const target = mod.getTarget();
3566 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3567 16 => .{ .f16 = @divTrunc(lhs.toFloat(f16, mod), rhs.toFloat(f16, mod)) },
3568 32 => .{ .f32 = @divTrunc(lhs.toFloat(f32, mod), rhs.toFloat(f32, mod)) },
3569 64 => .{ .f64 = @divTrunc(lhs.toFloat(f64, mod), rhs.toFloat(f64, mod)) },
3570 80 => .{ .f80 = @divTrunc(lhs.toFloat(f80, mod), rhs.toFloat(f80, mod)) },
3571 128 => .{ .f128 = @divTrunc(lhs.toFloat(f128, mod), rhs.toFloat(f128, mod)) },
46823572 else => unreachable,
4683 }
3573 };
3574 return (try mod.intern(.{ .float = .{
3575 .ty = float_type.toIntern(),
3576 .storage = storage,
3577 } })).toValue();
46843578 }
46853579
46863580 pub fn floatMul(
......@@ -4690,616 +3584,489 @@ pub const Value = extern union {
46903584 arena: Allocator,
46913585 mod: *Module,
46923586 ) !Value {
4693 const target = mod.getTarget();
4694 if (float_type.zigTypeTag() == .Vector) {
4695 const result_data = try arena.alloc(Value, float_type.vectorLen());
3587 if (float_type.zigTypeTag(mod) == .Vector) {
3588 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3589 const scalar_ty = float_type.scalarType(mod);
46963590 for (result_data, 0..) |*scalar, i| {
4697 var lhs_buf: Value.ElemValueBuffer = undefined;
4698 var rhs_buf: Value.ElemValueBuffer = undefined;
4699 const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
4700 const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
4701 scalar.* = try floatMulScalar(lhs_elem, rhs_elem, float_type.scalarType(), arena, target);
3591 const lhs_elem = try lhs.elemValue(mod, i);
3592 const rhs_elem = try rhs.elemValue(mod, i);
3593 scalar.* = try (try floatMulScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod);
47023594 }
4703 return Value.Tag.aggregate.create(arena, result_data);
3595 return (try mod.intern(.{ .aggregate = .{
3596 .ty = float_type.toIntern(),
3597 .storage = .{ .elems = result_data },
3598 } })).toValue();
47043599 }
4705 return floatMulScalar(lhs, rhs, float_type, arena, target);
3600 return floatMulScalar(lhs, rhs, float_type, mod);
47063601 }
47073602
47083603 pub fn floatMulScalar(
47093604 lhs: Value,
47103605 rhs: Value,
47113606 float_type: Type,
4712 arena: Allocator,
4713 target: Target,
3607 mod: *Module,
47143608 ) !Value {
4715 switch (float_type.floatBits(target)) {
4716 16 => {
4717 const lhs_val = lhs.toFloat(f16);
4718 const rhs_val = rhs.toFloat(f16);
4719 return Value.Tag.float_16.create(arena, lhs_val * rhs_val);
4720 },
4721 32 => {
4722 const lhs_val = lhs.toFloat(f32);
4723 const rhs_val = rhs.toFloat(f32);
4724 return Value.Tag.float_32.create(arena, lhs_val * rhs_val);
4725 },
4726 64 => {
4727 const lhs_val = lhs.toFloat(f64);
4728 const rhs_val = rhs.toFloat(f64);
4729 return Value.Tag.float_64.create(arena, lhs_val * rhs_val);
4730 },
4731 80 => {
4732 const lhs_val = lhs.toFloat(f80);
4733 const rhs_val = rhs.toFloat(f80);
4734 return Value.Tag.float_80.create(arena, lhs_val * rhs_val);
4735 },
4736 128 => {
4737 const lhs_val = lhs.toFloat(f128);
4738 const rhs_val = rhs.toFloat(f128);
4739 return Value.Tag.float_128.create(arena, lhs_val * rhs_val);
4740 },
3609 const target = mod.getTarget();
3610 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3611 16 => .{ .f16 = lhs.toFloat(f16, mod) * rhs.toFloat(f16, mod) },
3612 32 => .{ .f32 = lhs.toFloat(f32, mod) * rhs.toFloat(f32, mod) },
3613 64 => .{ .f64 = lhs.toFloat(f64, mod) * rhs.toFloat(f64, mod) },
3614 80 => .{ .f80 = lhs.toFloat(f80, mod) * rhs.toFloat(f80, mod) },
3615 128 => .{ .f128 = lhs.toFloat(f128, mod) * rhs.toFloat(f128, mod) },
47413616 else => unreachable,
4742 }
3617 };
3618 return (try mod.intern(.{ .float = .{
3619 .ty = float_type.toIntern(),
3620 .storage = storage,
3621 } })).toValue();
47433622 }
47443623
47453624 pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4746 const target = mod.getTarget();
4747 if (float_type.zigTypeTag() == .Vector) {
4748 const result_data = try arena.alloc(Value, float_type.vectorLen());
3625 if (float_type.zigTypeTag(mod) == .Vector) {
3626 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3627 const scalar_ty = float_type.scalarType(mod);
47493628 for (result_data, 0..) |*scalar, i| {
4750 var buf: Value.ElemValueBuffer = undefined;
4751 const elem_val = val.elemValueBuffer(mod, i, &buf);
4752 scalar.* = try sqrtScalar(elem_val, float_type.scalarType(), arena, target);
3629 const elem_val = try val.elemValue(mod, i);
3630 scalar.* = try (try sqrtScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
47533631 }
4754 return Value.Tag.aggregate.create(arena, result_data);
3632 return (try mod.intern(.{ .aggregate = .{
3633 .ty = float_type.toIntern(),
3634 .storage = .{ .elems = result_data },
3635 } })).toValue();
47553636 }
4756 return sqrtScalar(val, float_type, arena, target);
3637 return sqrtScalar(val, float_type, mod);
47573638 }
47583639
4759 pub fn sqrtScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4760 switch (float_type.floatBits(target)) {
4761 16 => {
4762 const f = val.toFloat(f16);
4763 return Value.Tag.float_16.create(arena, @sqrt(f));
4764 },
4765 32 => {
4766 const f = val.toFloat(f32);
4767 return Value.Tag.float_32.create(arena, @sqrt(f));
4768 },
4769 64 => {
4770 const f = val.toFloat(f64);
4771 return Value.Tag.float_64.create(arena, @sqrt(f));
4772 },
4773 80 => {
4774 const f = val.toFloat(f80);
4775 return Value.Tag.float_80.create(arena, @sqrt(f));
4776 },
4777 128 => {
4778 const f = val.toFloat(f128);
4779 return Value.Tag.float_128.create(arena, @sqrt(f));
4780 },
3640 pub fn sqrtScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3641 const target = mod.getTarget();
3642 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3643 16 => .{ .f16 = @sqrt(val.toFloat(f16, mod)) },
3644 32 => .{ .f32 = @sqrt(val.toFloat(f32, mod)) },
3645 64 => .{ .f64 = @sqrt(val.toFloat(f64, mod)) },
3646 80 => .{ .f80 = @sqrt(val.toFloat(f80, mod)) },
3647 128 => .{ .f128 = @sqrt(val.toFloat(f128, mod)) },
47813648 else => unreachable,
4782 }
3649 };
3650 return (try mod.intern(.{ .float = .{
3651 .ty = float_type.toIntern(),
3652 .storage = storage,
3653 } })).toValue();
47833654 }
47843655
47853656 pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4786 const target = mod.getTarget();
4787 if (float_type.zigTypeTag() == .Vector) {
4788 const result_data = try arena.alloc(Value, float_type.vectorLen());
3657 if (float_type.zigTypeTag(mod) == .Vector) {
3658 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3659 const scalar_ty = float_type.scalarType(mod);
47893660 for (result_data, 0..) |*scalar, i| {
4790 var buf: Value.ElemValueBuffer = undefined;
4791 const elem_val = val.elemValueBuffer(mod, i, &buf);
4792 scalar.* = try sinScalar(elem_val, float_type.scalarType(), arena, target);
3661 const elem_val = try val.elemValue(mod, i);
3662 scalar.* = try (try sinScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
47933663 }
4794 return Value.Tag.aggregate.create(arena, result_data);
3664 return (try mod.intern(.{ .aggregate = .{
3665 .ty = float_type.toIntern(),
3666 .storage = .{ .elems = result_data },
3667 } })).toValue();
47953668 }
4796 return sinScalar(val, float_type, arena, target);
3669 return sinScalar(val, float_type, mod);
47973670 }
47983671
4799 pub fn sinScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4800 switch (float_type.floatBits(target)) {
4801 16 => {
4802 const f = val.toFloat(f16);
4803 return Value.Tag.float_16.create(arena, @sin(f));
4804 },
4805 32 => {
4806 const f = val.toFloat(f32);
4807 return Value.Tag.float_32.create(arena, @sin(f));
4808 },
4809 64 => {
4810 const f = val.toFloat(f64);
4811 return Value.Tag.float_64.create(arena, @sin(f));
4812 },
4813 80 => {
4814 const f = val.toFloat(f80);
4815 return Value.Tag.float_80.create(arena, @sin(f));
4816 },
4817 128 => {
4818 const f = val.toFloat(f128);
4819 return Value.Tag.float_128.create(arena, @sin(f));
4820 },
3672 pub fn sinScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3673 const target = mod.getTarget();
3674 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3675 16 => .{ .f16 = @sin(val.toFloat(f16, mod)) },
3676 32 => .{ .f32 = @sin(val.toFloat(f32, mod)) },
3677 64 => .{ .f64 = @sin(val.toFloat(f64, mod)) },
3678 80 => .{ .f80 = @sin(val.toFloat(f80, mod)) },
3679 128 => .{ .f128 = @sin(val.toFloat(f128, mod)) },
48213680 else => unreachable,
4822 }
3681 };
3682 return (try mod.intern(.{ .float = .{
3683 .ty = float_type.toIntern(),
3684 .storage = storage,
3685 } })).toValue();
48233686 }
48243687
48253688 pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4826 const target = mod.getTarget();
4827 if (float_type.zigTypeTag() == .Vector) {
4828 const result_data = try arena.alloc(Value, float_type.vectorLen());
3689 if (float_type.zigTypeTag(mod) == .Vector) {
3690 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3691 const scalar_ty = float_type.scalarType(mod);
48293692 for (result_data, 0..) |*scalar, i| {
4830 var buf: Value.ElemValueBuffer = undefined;
4831 const elem_val = val.elemValueBuffer(mod, i, &buf);
4832 scalar.* = try cosScalar(elem_val, float_type.scalarType(), arena, target);
3693 const elem_val = try val.elemValue(mod, i);
3694 scalar.* = try (try cosScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
48333695 }
4834 return Value.Tag.aggregate.create(arena, result_data);
3696 return (try mod.intern(.{ .aggregate = .{
3697 .ty = float_type.toIntern(),
3698 .storage = .{ .elems = result_data },
3699 } })).toValue();
48353700 }
4836 return cosScalar(val, float_type, arena, target);
3701 return cosScalar(val, float_type, mod);
48373702 }
48383703
4839 pub fn cosScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4840 switch (float_type.floatBits(target)) {
4841 16 => {
4842 const f = val.toFloat(f16);
4843 return Value.Tag.float_16.create(arena, @cos(f));
4844 },
4845 32 => {
4846 const f = val.toFloat(f32);
4847 return Value.Tag.float_32.create(arena, @cos(f));
4848 },
4849 64 => {
4850 const f = val.toFloat(f64);
4851 return Value.Tag.float_64.create(arena, @cos(f));
4852 },
4853 80 => {
4854 const f = val.toFloat(f80);
4855 return Value.Tag.float_80.create(arena, @cos(f));
4856 },
4857 128 => {
4858 const f = val.toFloat(f128);
4859 return Value.Tag.float_128.create(arena, @cos(f));
4860 },
3704 pub fn cosScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3705 const target = mod.getTarget();
3706 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3707 16 => .{ .f16 = @cos(val.toFloat(f16, mod)) },
3708 32 => .{ .f32 = @cos(val.toFloat(f32, mod)) },
3709 64 => .{ .f64 = @cos(val.toFloat(f64, mod)) },
3710 80 => .{ .f80 = @cos(val.toFloat(f80, mod)) },
3711 128 => .{ .f128 = @cos(val.toFloat(f128, mod)) },
48613712 else => unreachable,
4862 }
3713 };
3714 return (try mod.intern(.{ .float = .{
3715 .ty = float_type.toIntern(),
3716 .storage = storage,
3717 } })).toValue();
48633718 }
48643719
48653720 pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4866 const target = mod.getTarget();
4867 if (float_type.zigTypeTag() == .Vector) {
4868 const result_data = try arena.alloc(Value, float_type.vectorLen());
3721 if (float_type.zigTypeTag(mod) == .Vector) {
3722 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3723 const scalar_ty = float_type.scalarType(mod);
48693724 for (result_data, 0..) |*scalar, i| {
4870 var buf: Value.ElemValueBuffer = undefined;
4871 const elem_val = val.elemValueBuffer(mod, i, &buf);
4872 scalar.* = try tanScalar(elem_val, float_type.scalarType(), arena, target);
3725 const elem_val = try val.elemValue(mod, i);
3726 scalar.* = try (try tanScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
48733727 }
4874 return Value.Tag.aggregate.create(arena, result_data);
3728 return (try mod.intern(.{ .aggregate = .{
3729 .ty = float_type.toIntern(),
3730 .storage = .{ .elems = result_data },
3731 } })).toValue();
48753732 }
4876 return tanScalar(val, float_type, arena, target);
3733 return tanScalar(val, float_type, mod);
48773734 }
48783735
4879 pub fn tanScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4880 switch (float_type.floatBits(target)) {
4881 16 => {
4882 const f = val.toFloat(f16);
4883 return Value.Tag.float_16.create(arena, @tan(f));
4884 },
4885 32 => {
4886 const f = val.toFloat(f32);
4887 return Value.Tag.float_32.create(arena, @tan(f));
4888 },
4889 64 => {
4890 const f = val.toFloat(f64);
4891 return Value.Tag.float_64.create(arena, @tan(f));
4892 },
4893 80 => {
4894 const f = val.toFloat(f80);
4895 return Value.Tag.float_80.create(arena, @tan(f));
4896 },
4897 128 => {
4898 const f = val.toFloat(f128);
4899 return Value.Tag.float_128.create(arena, @tan(f));
4900 },
3736 pub fn tanScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3737 const target = mod.getTarget();
3738 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3739 16 => .{ .f16 = @tan(val.toFloat(f16, mod)) },
3740 32 => .{ .f32 = @tan(val.toFloat(f32, mod)) },
3741 64 => .{ .f64 = @tan(val.toFloat(f64, mod)) },
3742 80 => .{ .f80 = @tan(val.toFloat(f80, mod)) },
3743 128 => .{ .f128 = @tan(val.toFloat(f128, mod)) },
49013744 else => unreachable,
4902 }
3745 };
3746 return (try mod.intern(.{ .float = .{
3747 .ty = float_type.toIntern(),
3748 .storage = storage,
3749 } })).toValue();
49033750 }
49043751
49053752 pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4906 const target = mod.getTarget();
4907 if (float_type.zigTypeTag() == .Vector) {
4908 const result_data = try arena.alloc(Value, float_type.vectorLen());
3753 if (float_type.zigTypeTag(mod) == .Vector) {
3754 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3755 const scalar_ty = float_type.scalarType(mod);
49093756 for (result_data, 0..) |*scalar, i| {
4910 var buf: Value.ElemValueBuffer = undefined;
4911 const elem_val = val.elemValueBuffer(mod, i, &buf);
4912 scalar.* = try expScalar(elem_val, float_type.scalarType(), arena, target);
3757 const elem_val = try val.elemValue(mod, i);
3758 scalar.* = try (try expScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
49133759 }
4914 return Value.Tag.aggregate.create(arena, result_data);
3760 return (try mod.intern(.{ .aggregate = .{
3761 .ty = float_type.toIntern(),
3762 .storage = .{ .elems = result_data },
3763 } })).toValue();
49153764 }
4916 return expScalar(val, float_type, arena, target);
3765 return expScalar(val, float_type, mod);
49173766 }
49183767
4919 pub fn expScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4920 switch (float_type.floatBits(target)) {
4921 16 => {
4922 const f = val.toFloat(f16);
4923 return Value.Tag.float_16.create(arena, @exp(f));
4924 },
4925 32 => {
4926 const f = val.toFloat(f32);
4927 return Value.Tag.float_32.create(arena, @exp(f));
4928 },
4929 64 => {
4930 const f = val.toFloat(f64);
4931 return Value.Tag.float_64.create(arena, @exp(f));
4932 },
4933 80 => {
4934 const f = val.toFloat(f80);
4935 return Value.Tag.float_80.create(arena, @exp(f));
4936 },
4937 128 => {
4938 const f = val.toFloat(f128);
4939 return Value.Tag.float_128.create(arena, @exp(f));
4940 },
3768 pub fn expScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3769 const target = mod.getTarget();
3770 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3771 16 => .{ .f16 = @exp(val.toFloat(f16, mod)) },
3772 32 => .{ .f32 = @exp(val.toFloat(f32, mod)) },
3773 64 => .{ .f64 = @exp(val.toFloat(f64, mod)) },
3774 80 => .{ .f80 = @exp(val.toFloat(f80, mod)) },
3775 128 => .{ .f128 = @exp(val.toFloat(f128, mod)) },
49413776 else => unreachable,
4942 }
3777 };
3778 return (try mod.intern(.{ .float = .{
3779 .ty = float_type.toIntern(),
3780 .storage = storage,
3781 } })).toValue();
49433782 }
49443783
49453784 pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4946 const target = mod.getTarget();
4947 if (float_type.zigTypeTag() == .Vector) {
4948 const result_data = try arena.alloc(Value, float_type.vectorLen());
3785 if (float_type.zigTypeTag(mod) == .Vector) {
3786 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3787 const scalar_ty = float_type.scalarType(mod);
49493788 for (result_data, 0..) |*scalar, i| {
4950 var buf: Value.ElemValueBuffer = undefined;
4951 const elem_val = val.elemValueBuffer(mod, i, &buf);
4952 scalar.* = try exp2Scalar(elem_val, float_type.scalarType(), arena, target);
3789 const elem_val = try val.elemValue(mod, i);
3790 scalar.* = try (try exp2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
49533791 }
4954 return Value.Tag.aggregate.create(arena, result_data);
3792 return (try mod.intern(.{ .aggregate = .{
3793 .ty = float_type.toIntern(),
3794 .storage = .{ .elems = result_data },
3795 } })).toValue();
49553796 }
4956 return exp2Scalar(val, float_type, arena, target);
3797 return exp2Scalar(val, float_type, mod);
49573798 }
49583799
4959 pub fn exp2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
4960 switch (float_type.floatBits(target)) {
4961 16 => {
4962 const f = val.toFloat(f16);
4963 return Value.Tag.float_16.create(arena, @exp2(f));
4964 },
4965 32 => {
4966 const f = val.toFloat(f32);
4967 return Value.Tag.float_32.create(arena, @exp2(f));
4968 },
4969 64 => {
4970 const f = val.toFloat(f64);
4971 return Value.Tag.float_64.create(arena, @exp2(f));
4972 },
4973 80 => {
4974 const f = val.toFloat(f80);
4975 return Value.Tag.float_80.create(arena, @exp2(f));
4976 },
4977 128 => {
4978 const f = val.toFloat(f128);
4979 return Value.Tag.float_128.create(arena, @exp2(f));
4980 },
3800 pub fn exp2Scalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3801 const target = mod.getTarget();
3802 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3803 16 => .{ .f16 = @exp2(val.toFloat(f16, mod)) },
3804 32 => .{ .f32 = @exp2(val.toFloat(f32, mod)) },
3805 64 => .{ .f64 = @exp2(val.toFloat(f64, mod)) },
3806 80 => .{ .f80 = @exp2(val.toFloat(f80, mod)) },
3807 128 => .{ .f128 = @exp2(val.toFloat(f128, mod)) },
49813808 else => unreachable,
4982 }
3809 };
3810 return (try mod.intern(.{ .float = .{
3811 .ty = float_type.toIntern(),
3812 .storage = storage,
3813 } })).toValue();
49833814 }
49843815
49853816 pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
4986 const target = mod.getTarget();
4987 if (float_type.zigTypeTag() == .Vector) {
4988 const result_data = try arena.alloc(Value, float_type.vectorLen());
3817 if (float_type.zigTypeTag(mod) == .Vector) {
3818 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3819 const scalar_ty = float_type.scalarType(mod);
49893820 for (result_data, 0..) |*scalar, i| {
4990 var buf: Value.ElemValueBuffer = undefined;
4991 const elem_val = val.elemValueBuffer(mod, i, &buf);
4992 scalar.* = try logScalar(elem_val, float_type.scalarType(), arena, target);
3821 const elem_val = try val.elemValue(mod, i);
3822 scalar.* = try (try logScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
49933823 }
4994 return Value.Tag.aggregate.create(arena, result_data);
3824 return (try mod.intern(.{ .aggregate = .{
3825 .ty = float_type.toIntern(),
3826 .storage = .{ .elems = result_data },
3827 } })).toValue();
49953828 }
4996 return logScalar(val, float_type, arena, target);
3829 return logScalar(val, float_type, mod);
49973830 }
49983831
4999 pub fn logScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5000 switch (float_type.floatBits(target)) {
5001 16 => {
5002 const f = val.toFloat(f16);
5003 return Value.Tag.float_16.create(arena, @log(f));
5004 },
5005 32 => {
5006 const f = val.toFloat(f32);
5007 return Value.Tag.float_32.create(arena, @log(f));
5008 },
5009 64 => {
5010 const f = val.toFloat(f64);
5011 return Value.Tag.float_64.create(arena, @log(f));
5012 },
5013 80 => {
5014 const f = val.toFloat(f80);
5015 return Value.Tag.float_80.create(arena, @log(f));
5016 },
5017 128 => {
5018 const f = val.toFloat(f128);
5019 return Value.Tag.float_128.create(arena, @log(f));
5020 },
3832 pub fn logScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3833 const target = mod.getTarget();
3834 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3835 16 => .{ .f16 = @log(val.toFloat(f16, mod)) },
3836 32 => .{ .f32 = @log(val.toFloat(f32, mod)) },
3837 64 => .{ .f64 = @log(val.toFloat(f64, mod)) },
3838 80 => .{ .f80 = @log(val.toFloat(f80, mod)) },
3839 128 => .{ .f128 = @log(val.toFloat(f128, mod)) },
50213840 else => unreachable,
5022 }
3841 };
3842 return (try mod.intern(.{ .float = .{
3843 .ty = float_type.toIntern(),
3844 .storage = storage,
3845 } })).toValue();
50233846 }
50243847
50253848 pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5026 const target = mod.getTarget();
5027 if (float_type.zigTypeTag() == .Vector) {
5028 const result_data = try arena.alloc(Value, float_type.vectorLen());
3849 if (float_type.zigTypeTag(mod) == .Vector) {
3850 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3851 const scalar_ty = float_type.scalarType(mod);
50293852 for (result_data, 0..) |*scalar, i| {
5030 var buf: Value.ElemValueBuffer = undefined;
5031 const elem_val = val.elemValueBuffer(mod, i, &buf);
5032 scalar.* = try log2Scalar(elem_val, float_type.scalarType(), arena, target);
3853 const elem_val = try val.elemValue(mod, i);
3854 scalar.* = try (try log2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
50333855 }
5034 return Value.Tag.aggregate.create(arena, result_data);
3856 return (try mod.intern(.{ .aggregate = .{
3857 .ty = float_type.toIntern(),
3858 .storage = .{ .elems = result_data },
3859 } })).toValue();
50353860 }
5036 return log2Scalar(val, float_type, arena, target);
3861 return log2Scalar(val, float_type, mod);
50373862 }
50383863
5039 pub fn log2Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5040 switch (float_type.floatBits(target)) {
5041 16 => {
5042 const f = val.toFloat(f16);
5043 return Value.Tag.float_16.create(arena, @log2(f));
5044 },
5045 32 => {
5046 const f = val.toFloat(f32);
5047 return Value.Tag.float_32.create(arena, @log2(f));
5048 },
5049 64 => {
5050 const f = val.toFloat(f64);
5051 return Value.Tag.float_64.create(arena, @log2(f));
5052 },
5053 80 => {
5054 const f = val.toFloat(f80);
5055 return Value.Tag.float_80.create(arena, @log2(f));
5056 },
5057 128 => {
5058 const f = val.toFloat(f128);
5059 return Value.Tag.float_128.create(arena, @log2(f));
5060 },
3864 pub fn log2Scalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3865 const target = mod.getTarget();
3866 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3867 16 => .{ .f16 = @log2(val.toFloat(f16, mod)) },
3868 32 => .{ .f32 = @log2(val.toFloat(f32, mod)) },
3869 64 => .{ .f64 = @log2(val.toFloat(f64, mod)) },
3870 80 => .{ .f80 = @log2(val.toFloat(f80, mod)) },
3871 128 => .{ .f128 = @log2(val.toFloat(f128, mod)) },
50613872 else => unreachable,
5062 }
3873 };
3874 return (try mod.intern(.{ .float = .{
3875 .ty = float_type.toIntern(),
3876 .storage = storage,
3877 } })).toValue();
50633878 }
50643879
50653880 pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5066 const target = mod.getTarget();
5067 if (float_type.zigTypeTag() == .Vector) {
5068 const result_data = try arena.alloc(Value, float_type.vectorLen());
3881 if (float_type.zigTypeTag(mod) == .Vector) {
3882 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3883 const scalar_ty = float_type.scalarType(mod);
50693884 for (result_data, 0..) |*scalar, i| {
5070 var buf: Value.ElemValueBuffer = undefined;
5071 const elem_val = val.elemValueBuffer(mod, i, &buf);
5072 scalar.* = try log10Scalar(elem_val, float_type.scalarType(), arena, target);
3885 const elem_val = try val.elemValue(mod, i);
3886 scalar.* = try (try log10Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
50733887 }
5074 return Value.Tag.aggregate.create(arena, result_data);
3888 return (try mod.intern(.{ .aggregate = .{
3889 .ty = float_type.toIntern(),
3890 .storage = .{ .elems = result_data },
3891 } })).toValue();
50753892 }
5076 return log10Scalar(val, float_type, arena, target);
3893 return log10Scalar(val, float_type, mod);
50773894 }
50783895
5079 pub fn log10Scalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5080 switch (float_type.floatBits(target)) {
5081 16 => {
5082 const f = val.toFloat(f16);
5083 return Value.Tag.float_16.create(arena, @log10(f));
5084 },
5085 32 => {
5086 const f = val.toFloat(f32);
5087 return Value.Tag.float_32.create(arena, @log10(f));
5088 },
5089 64 => {
5090 const f = val.toFloat(f64);
5091 return Value.Tag.float_64.create(arena, @log10(f));
5092 },
5093 80 => {
5094 const f = val.toFloat(f80);
5095 return Value.Tag.float_80.create(arena, @log10(f));
5096 },
5097 128 => {
5098 const f = val.toFloat(f128);
5099 return Value.Tag.float_128.create(arena, @log10(f));
5100 },
3896 pub fn log10Scalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3897 const target = mod.getTarget();
3898 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3899 16 => .{ .f16 = @log10(val.toFloat(f16, mod)) },
3900 32 => .{ .f32 = @log10(val.toFloat(f32, mod)) },
3901 64 => .{ .f64 = @log10(val.toFloat(f64, mod)) },
3902 80 => .{ .f80 = @log10(val.toFloat(f80, mod)) },
3903 128 => .{ .f128 = @log10(val.toFloat(f128, mod)) },
51013904 else => unreachable,
5102 }
3905 };
3906 return (try mod.intern(.{ .float = .{
3907 .ty = float_type.toIntern(),
3908 .storage = storage,
3909 } })).toValue();
51033910 }
51043911
51053912 pub fn fabs(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5106 const target = mod.getTarget();
5107 if (float_type.zigTypeTag() == .Vector) {
5108 const result_data = try arena.alloc(Value, float_type.vectorLen());
3913 if (float_type.zigTypeTag(mod) == .Vector) {
3914 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3915 const scalar_ty = float_type.scalarType(mod);
51093916 for (result_data, 0..) |*scalar, i| {
5110 var buf: Value.ElemValueBuffer = undefined;
5111 const elem_val = val.elemValueBuffer(mod, i, &buf);
5112 scalar.* = try fabsScalar(elem_val, float_type.scalarType(), arena, target);
3917 const elem_val = try val.elemValue(mod, i);
3918 scalar.* = try (try fabsScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
51133919 }
5114 return Value.Tag.aggregate.create(arena, result_data);
3920 return (try mod.intern(.{ .aggregate = .{
3921 .ty = float_type.toIntern(),
3922 .storage = .{ .elems = result_data },
3923 } })).toValue();
51153924 }
5116 return fabsScalar(val, float_type, arena, target);
3925 return fabsScalar(val, float_type, mod);
51173926 }
51183927
5119 pub fn fabsScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5120 switch (float_type.floatBits(target)) {
5121 16 => {
5122 const f = val.toFloat(f16);
5123 return Value.Tag.float_16.create(arena, @fabs(f));
5124 },
5125 32 => {
5126 const f = val.toFloat(f32);
5127 return Value.Tag.float_32.create(arena, @fabs(f));
5128 },
5129 64 => {
5130 const f = val.toFloat(f64);
5131 return Value.Tag.float_64.create(arena, @fabs(f));
5132 },
5133 80 => {
5134 const f = val.toFloat(f80);
5135 return Value.Tag.float_80.create(arena, @fabs(f));
5136 },
5137 128 => {
5138 const f = val.toFloat(f128);
5139 return Value.Tag.float_128.create(arena, @fabs(f));
5140 },
3928 pub fn fabsScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3929 const target = mod.getTarget();
3930 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3931 16 => .{ .f16 = @fabs(val.toFloat(f16, mod)) },
3932 32 => .{ .f32 = @fabs(val.toFloat(f32, mod)) },
3933 64 => .{ .f64 = @fabs(val.toFloat(f64, mod)) },
3934 80 => .{ .f80 = @fabs(val.toFloat(f80, mod)) },
3935 128 => .{ .f128 = @fabs(val.toFloat(f128, mod)) },
51413936 else => unreachable,
5142 }
3937 };
3938 return (try mod.intern(.{ .float = .{
3939 .ty = float_type.toIntern(),
3940 .storage = storage,
3941 } })).toValue();
51433942 }
51443943
51453944 pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5146 const target = mod.getTarget();
5147 if (float_type.zigTypeTag() == .Vector) {
5148 const result_data = try arena.alloc(Value, float_type.vectorLen());
3945 if (float_type.zigTypeTag(mod) == .Vector) {
3946 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3947 const scalar_ty = float_type.scalarType(mod);
51493948 for (result_data, 0..) |*scalar, i| {
5150 var buf: Value.ElemValueBuffer = undefined;
5151 const elem_val = val.elemValueBuffer(mod, i, &buf);
5152 scalar.* = try floorScalar(elem_val, float_type.scalarType(), arena, target);
3949 const elem_val = try val.elemValue(mod, i);
3950 scalar.* = try (try floorScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
51533951 }
5154 return Value.Tag.aggregate.create(arena, result_data);
3952 return (try mod.intern(.{ .aggregate = .{
3953 .ty = float_type.toIntern(),
3954 .storage = .{ .elems = result_data },
3955 } })).toValue();
51553956 }
5156 return floorScalar(val, float_type, arena, target);
3957 return floorScalar(val, float_type, mod);
51573958 }
51583959
5159 pub fn floorScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5160 switch (float_type.floatBits(target)) {
5161 16 => {
5162 const f = val.toFloat(f16);
5163 return Value.Tag.float_16.create(arena, @floor(f));
5164 },
5165 32 => {
5166 const f = val.toFloat(f32);
5167 return Value.Tag.float_32.create(arena, @floor(f));
5168 },
5169 64 => {
5170 const f = val.toFloat(f64);
5171 return Value.Tag.float_64.create(arena, @floor(f));
5172 },
5173 80 => {
5174 const f = val.toFloat(f80);
5175 return Value.Tag.float_80.create(arena, @floor(f));
5176 },
5177 128 => {
5178 const f = val.toFloat(f128);
5179 return Value.Tag.float_128.create(arena, @floor(f));
5180 },
3960 pub fn floorScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3961 const target = mod.getTarget();
3962 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3963 16 => .{ .f16 = @floor(val.toFloat(f16, mod)) },
3964 32 => .{ .f32 = @floor(val.toFloat(f32, mod)) },
3965 64 => .{ .f64 = @floor(val.toFloat(f64, mod)) },
3966 80 => .{ .f80 = @floor(val.toFloat(f80, mod)) },
3967 128 => .{ .f128 = @floor(val.toFloat(f128, mod)) },
51813968 else => unreachable,
5182 }
3969 };
3970 return (try mod.intern(.{ .float = .{
3971 .ty = float_type.toIntern(),
3972 .storage = storage,
3973 } })).toValue();
51833974 }
51843975
51853976 pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5186 const target = mod.getTarget();
5187 if (float_type.zigTypeTag() == .Vector) {
5188 const result_data = try arena.alloc(Value, float_type.vectorLen());
3977 if (float_type.zigTypeTag(mod) == .Vector) {
3978 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
3979 const scalar_ty = float_type.scalarType(mod);
51893980 for (result_data, 0..) |*scalar, i| {
5190 var buf: Value.ElemValueBuffer = undefined;
5191 const elem_val = val.elemValueBuffer(mod, i, &buf);
5192 scalar.* = try ceilScalar(elem_val, float_type.scalarType(), arena, target);
3981 const elem_val = try val.elemValue(mod, i);
3982 scalar.* = try (try ceilScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
51933983 }
5194 return Value.Tag.aggregate.create(arena, result_data);
3984 return (try mod.intern(.{ .aggregate = .{
3985 .ty = float_type.toIntern(),
3986 .storage = .{ .elems = result_data },
3987 } })).toValue();
51953988 }
5196 return ceilScalar(val, float_type, arena, target);
3989 return ceilScalar(val, float_type, mod);
51973990 }
51983991
5199 pub fn ceilScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5200 switch (float_type.floatBits(target)) {
5201 16 => {
5202 const f = val.toFloat(f16);
5203 return Value.Tag.float_16.create(arena, @ceil(f));
5204 },
5205 32 => {
5206 const f = val.toFloat(f32);
5207 return Value.Tag.float_32.create(arena, @ceil(f));
5208 },
5209 64 => {
5210 const f = val.toFloat(f64);
5211 return Value.Tag.float_64.create(arena, @ceil(f));
5212 },
5213 80 => {
5214 const f = val.toFloat(f80);
5215 return Value.Tag.float_80.create(arena, @ceil(f));
5216 },
5217 128 => {
5218 const f = val.toFloat(f128);
5219 return Value.Tag.float_128.create(arena, @ceil(f));
5220 },
3992 pub fn ceilScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
3993 const target = mod.getTarget();
3994 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
3995 16 => .{ .f16 = @ceil(val.toFloat(f16, mod)) },
3996 32 => .{ .f32 = @ceil(val.toFloat(f32, mod)) },
3997 64 => .{ .f64 = @ceil(val.toFloat(f64, mod)) },
3998 80 => .{ .f80 = @ceil(val.toFloat(f80, mod)) },
3999 128 => .{ .f128 = @ceil(val.toFloat(f128, mod)) },
52214000 else => unreachable,
5222 }
4001 };
4002 return (try mod.intern(.{ .float = .{
4003 .ty = float_type.toIntern(),
4004 .storage = storage,
4005 } })).toValue();
52234006 }
52244007
52254008 pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5226 const target = mod.getTarget();
5227 if (float_type.zigTypeTag() == .Vector) {
5228 const result_data = try arena.alloc(Value, float_type.vectorLen());
4009 if (float_type.zigTypeTag(mod) == .Vector) {
4010 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4011 const scalar_ty = float_type.scalarType(mod);
52294012 for (result_data, 0..) |*scalar, i| {
5230 var buf: Value.ElemValueBuffer = undefined;
5231 const elem_val = val.elemValueBuffer(mod, i, &buf);
5232 scalar.* = try roundScalar(elem_val, float_type.scalarType(), arena, target);
4013 const elem_val = try val.elemValue(mod, i);
4014 scalar.* = try (try roundScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
52334015 }
5234 return Value.Tag.aggregate.create(arena, result_data);
4016 return (try mod.intern(.{ .aggregate = .{
4017 .ty = float_type.toIntern(),
4018 .storage = .{ .elems = result_data },
4019 } })).toValue();
52354020 }
5236 return roundScalar(val, float_type, arena, target);
4021 return roundScalar(val, float_type, mod);
52374022 }
52384023
5239 pub fn roundScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5240 switch (float_type.floatBits(target)) {
5241 16 => {
5242 const f = val.toFloat(f16);
5243 return Value.Tag.float_16.create(arena, @round(f));
5244 },
5245 32 => {
5246 const f = val.toFloat(f32);
5247 return Value.Tag.float_32.create(arena, @round(f));
5248 },
5249 64 => {
5250 const f = val.toFloat(f64);
5251 return Value.Tag.float_64.create(arena, @round(f));
5252 },
5253 80 => {
5254 const f = val.toFloat(f80);
5255 return Value.Tag.float_80.create(arena, @round(f));
5256 },
5257 128 => {
5258 const f = val.toFloat(f128);
5259 return Value.Tag.float_128.create(arena, @round(f));
5260 },
4024 pub fn roundScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4025 const target = mod.getTarget();
4026 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4027 16 => .{ .f16 = @round(val.toFloat(f16, mod)) },
4028 32 => .{ .f32 = @round(val.toFloat(f32, mod)) },
4029 64 => .{ .f64 = @round(val.toFloat(f64, mod)) },
4030 80 => .{ .f80 = @round(val.toFloat(f80, mod)) },
4031 128 => .{ .f128 = @round(val.toFloat(f128, mod)) },
52614032 else => unreachable,
5262 }
4033 };
4034 return (try mod.intern(.{ .float = .{
4035 .ty = float_type.toIntern(),
4036 .storage = storage,
4037 } })).toValue();
52634038 }
52644039
52654040 pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value {
5266 const target = mod.getTarget();
5267 if (float_type.zigTypeTag() == .Vector) {
5268 const result_data = try arena.alloc(Value, float_type.vectorLen());
4041 if (float_type.zigTypeTag(mod) == .Vector) {
4042 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4043 const scalar_ty = float_type.scalarType(mod);
52694044 for (result_data, 0..) |*scalar, i| {
5270 var buf: Value.ElemValueBuffer = undefined;
5271 const elem_val = val.elemValueBuffer(mod, i, &buf);
5272 scalar.* = try truncScalar(elem_val, float_type.scalarType(), arena, target);
4045 const elem_val = try val.elemValue(mod, i);
4046 scalar.* = try (try truncScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod);
52734047 }
5274 return Value.Tag.aggregate.create(arena, result_data);
4048 return (try mod.intern(.{ .aggregate = .{
4049 .ty = float_type.toIntern(),
4050 .storage = .{ .elems = result_data },
4051 } })).toValue();
52754052 }
5276 return truncScalar(val, float_type, arena, target);
4053 return truncScalar(val, float_type, mod);
52774054 }
52784055
5279 pub fn truncScalar(val: Value, float_type: Type, arena: Allocator, target: Target) Allocator.Error!Value {
5280 switch (float_type.floatBits(target)) {
5281 16 => {
5282 const f = val.toFloat(f16);
5283 return Value.Tag.float_16.create(arena, @trunc(f));
5284 },
5285 32 => {
5286 const f = val.toFloat(f32);
5287 return Value.Tag.float_32.create(arena, @trunc(f));
5288 },
5289 64 => {
5290 const f = val.toFloat(f64);
5291 return Value.Tag.float_64.create(arena, @trunc(f));
5292 },
5293 80 => {
5294 const f = val.toFloat(f80);
5295 return Value.Tag.float_80.create(arena, @trunc(f));
5296 },
5297 128 => {
5298 const f = val.toFloat(f128);
5299 return Value.Tag.float_128.create(arena, @trunc(f));
5300 },
4056 pub fn truncScalar(val: Value, float_type: Type, mod: *Module) Allocator.Error!Value {
4057 const target = mod.getTarget();
4058 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4059 16 => .{ .f16 = @trunc(val.toFloat(f16, mod)) },
4060 32 => .{ .f32 = @trunc(val.toFloat(f32, mod)) },
4061 64 => .{ .f64 = @trunc(val.toFloat(f64, mod)) },
4062 80 => .{ .f80 = @trunc(val.toFloat(f80, mod)) },
4063 128 => .{ .f128 = @trunc(val.toFloat(f128, mod)) },
53014064 else => unreachable,
5302 }
4065 };
4066 return (try mod.intern(.{ .float = .{
4067 .ty = float_type.toIntern(),
4068 .storage = storage,
4069 } })).toValue();
53034070 }
53044071
53054072 pub fn mulAdd(
......@@ -5310,28 +4077,21 @@ pub const Value = extern union {
53104077 arena: Allocator,
53114078 mod: *Module,
53124079 ) !Value {
5313 const target = mod.getTarget();
5314 if (float_type.zigTypeTag() == .Vector) {
5315 const result_data = try arena.alloc(Value, float_type.vectorLen());
4080 if (float_type.zigTypeTag(mod) == .Vector) {
4081 const result_data = try arena.alloc(InternPool.Index, float_type.vectorLen(mod));
4082 const scalar_ty = float_type.scalarType(mod);
53164083 for (result_data, 0..) |*scalar, i| {
5317 var mulend1_buf: Value.ElemValueBuffer = undefined;
5318 const mulend1_elem = mulend1.elemValueBuffer(mod, i, &mulend1_buf);
5319 var mulend2_buf: Value.ElemValueBuffer = undefined;
5320 const mulend2_elem = mulend2.elemValueBuffer(mod, i, &mulend2_buf);
5321 var addend_buf: Value.ElemValueBuffer = undefined;
5322 const addend_elem = addend.elemValueBuffer(mod, i, &addend_buf);
5323 scalar.* = try mulAddScalar(
5324 float_type.scalarType(),
5325 mulend1_elem,
5326 mulend2_elem,
5327 addend_elem,
5328 arena,
5329 target,
5330 );
4084 const mulend1_elem = try mulend1.elemValue(mod, i);
4085 const mulend2_elem = try mulend2.elemValue(mod, i);
4086 const addend_elem = try addend.elemValue(mod, i);
4087 scalar.* = try (try mulAddScalar(scalar_ty, mulend1_elem, mulend2_elem, addend_elem, mod)).intern(scalar_ty, mod);
53314088 }
5332 return Value.Tag.aggregate.create(arena, result_data);
4089 return (try mod.intern(.{ .aggregate = .{
4090 .ty = float_type.toIntern(),
4091 .storage = .{ .elems = result_data },
4092 } })).toValue();
53334093 }
5334 return mulAddScalar(float_type, mulend1, mulend2, addend, arena, target);
4094 return mulAddScalar(float_type, mulend1, mulend2, addend, mod);
53354095 }
53364096
53374097 pub fn mulAddScalar(
......@@ -5339,54 +4099,33 @@ pub const Value = extern union {
53394099 mulend1: Value,
53404100 mulend2: Value,
53414101 addend: Value,
5342 arena: Allocator,
5343 target: Target,
4102 mod: *Module,
53444103 ) Allocator.Error!Value {
5345 switch (float_type.floatBits(target)) {
5346 16 => {
5347 const m1 = mulend1.toFloat(f16);
5348 const m2 = mulend2.toFloat(f16);
5349 const a = addend.toFloat(f16);
5350 return Value.Tag.float_16.create(arena, @mulAdd(f16, m1, m2, a));
5351 },
5352 32 => {
5353 const m1 = mulend1.toFloat(f32);
5354 const m2 = mulend2.toFloat(f32);
5355 const a = addend.toFloat(f32);
5356 return Value.Tag.float_32.create(arena, @mulAdd(f32, m1, m2, a));
5357 },
5358 64 => {
5359 const m1 = mulend1.toFloat(f64);
5360 const m2 = mulend2.toFloat(f64);
5361 const a = addend.toFloat(f64);
5362 return Value.Tag.float_64.create(arena, @mulAdd(f64, m1, m2, a));
5363 },
5364 80 => {
5365 const m1 = mulend1.toFloat(f80);
5366 const m2 = mulend2.toFloat(f80);
5367 const a = addend.toFloat(f80);
5368 return Value.Tag.float_80.create(arena, @mulAdd(f80, m1, m2, a));
5369 },
5370 128 => {
5371 const m1 = mulend1.toFloat(f128);
5372 const m2 = mulend2.toFloat(f128);
5373 const a = addend.toFloat(f128);
5374 return Value.Tag.float_128.create(arena, @mulAdd(f128, m1, m2, a));
5375 },
4104 const target = mod.getTarget();
4105 const storage: InternPool.Key.Float.Storage = switch (float_type.floatBits(target)) {
4106 16 => .{ .f16 = @mulAdd(f16, mulend1.toFloat(f16, mod), mulend2.toFloat(f16, mod), addend.toFloat(f16, mod)) },
4107 32 => .{ .f32 = @mulAdd(f32, mulend1.toFloat(f32, mod), mulend2.toFloat(f32, mod), addend.toFloat(f32, mod)) },
4108 64 => .{ .f64 = @mulAdd(f64, mulend1.toFloat(f64, mod), mulend2.toFloat(f64, mod), addend.toFloat(f64, mod)) },
4109 80 => .{ .f80 = @mulAdd(f80, mulend1.toFloat(f80, mod), mulend2.toFloat(f80, mod), addend.toFloat(f80, mod)) },
4110 128 => .{ .f128 = @mulAdd(f128, mulend1.toFloat(f128, mod), mulend2.toFloat(f128, mod), addend.toFloat(f128, mod)) },
53764111 else => unreachable,
5377 }
4112 };
4113 return (try mod.intern(.{ .float = .{
4114 .ty = float_type.toIntern(),
4115 .storage = storage,
4116 } })).toValue();
53784117 }
53794118
53804119 /// If the value is represented in-memory as a series of bytes that all
53814120 /// have the same value, return that byte value, otherwise null.
5382 pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module, value_buffer: *Payload.U64) !?Value {
5383 const target = mod.getTarget();
5384 const abi_size = std.math.cast(usize, ty.abiSize(target)) orelse return null;
4121 pub fn hasRepeatedByteRepr(val: Value, ty: Type, mod: *Module) !?Value {
4122 const abi_size = std.math.cast(usize, ty.abiSize(mod)) orelse return null;
53854123 assert(abi_size >= 1);
53864124 const byte_buffer = try mod.gpa.alloc(u8, abi_size);
53874125 defer mod.gpa.free(byte_buffer);
53884126
53894127 writeToMemory(val, ty, mod, byte_buffer) catch |err| switch (err) {
4128 error.OutOfMemory => return error.OutOfMemory,
53904129 error.ReinterpretDeclRef => return null,
53914130 // TODO: The writeToMemory function was originally created for the purpose
53924131 // of comptime pointer casting. However, it is now additionally being used
......@@ -5400,118 +4139,22 @@ pub const Value = extern union {
54004139 for (byte_buffer[1..]) |byte| {
54014140 if (byte != first_byte) return null;
54024141 }
5403 value_buffer.* = .{
5404 .base = .{ .tag = .int_u64 },
5405 .data = first_byte,
5406 };
5407 return initPayload(&value_buffer.base);
4142 return try mod.intValue(Type.u8, first_byte);
4143 }
4144
4145 pub fn isGenericPoison(val: Value) bool {
4146 return val.toIntern() == .generic_poison;
54084147 }
54094148
54104149 /// This type is not copyable since it may contain pointers to its inner data.
54114150 pub const Payload = struct {
54124151 tag: Tag,
54134152
5414 pub const U32 = struct {
5415 base: Payload,
5416 data: u32,
5417 };
5418
5419 pub const U64 = struct {
5420 base: Payload,
5421 data: u64,
5422 };
5423
5424 pub const I64 = struct {
5425 base: Payload,
5426 data: i64,
5427 };
5428
5429 pub const BigInt = struct {
5430 base: Payload,
5431 data: []const std.math.big.Limb,
5432
5433 pub fn asBigInt(self: BigInt) BigIntConst {
5434 const positive = switch (self.base.tag) {
5435 .int_big_positive => true,
5436 .int_big_negative => false,
5437 else => unreachable,
5438 };
5439 return BigIntConst{ .limbs = self.data, .positive = positive };
5440 }
5441 };
5442
5443 pub const Function = struct {
5444 base: Payload,
5445 data: *Module.Fn,
5446 };
5447
5448 pub const ExternFn = struct {
5449 base: Payload,
5450 data: *Module.ExternFn,
5451 };
5452
5453 pub const Decl = struct {
5454 base: Payload,
5455 data: Module.Decl.Index,
5456 };
5457
5458 pub const Variable = struct {
5459 base: Payload,
5460 data: *Module.Var,
5461 };
5462
5463 pub const SubValue = struct {
5464 base: Payload,
5465 data: Value,
5466 };
5467
5468 pub const DeclRefMut = struct {
5469 pub const base_tag = Tag.decl_ref_mut;
5470
5471 base: Payload = Payload{ .tag = base_tag },
5472 data: Data,
5473
5474 pub const Data = struct {
5475 decl_index: Module.Decl.Index,
5476 runtime_index: RuntimeIndex,
5477 };
5478 };
5479
5480 pub const PayloadPtr = struct {
5481 base: Payload,
5482 data: struct {
5483 container_ptr: Value,
5484 container_ty: Type,
5485 },
5486 };
5487
5488 pub const ComptimeFieldPtr = struct {
4153 pub const Slice = struct {
54894154 base: Payload,
54904155 data: struct {
5491 field_val: Value,
5492 field_ty: Type,
5493 },
5494 };
5495
5496 pub const ElemPtr = struct {
5497 pub const base_tag = Tag.elem_ptr;
5498
5499 base: Payload = Payload{ .tag = base_tag },
5500 data: struct {
5501 array_ptr: Value,
5502 elem_ty: Type,
5503 index: usize,
5504 },
5505 };
5506
5507 pub const FieldPtr = struct {
5508 pub const base_tag = Tag.field_ptr;
5509
5510 base: Payload = Payload{ .tag = base_tag },
5511 data: struct {
5512 container_ptr: Value,
5513 container_ty: Type,
5514 field_index: usize,
4156 ptr: Value,
4157 len: Value,
55154158 },
55164159 };
55174160
......@@ -5521,9 +4164,9 @@ pub const Value = extern union {
55214164 data: []const u8,
55224165 };
55234166
5524 pub const StrLit = struct {
4167 pub const SubValue = struct {
55254168 base: Payload,
5526 data: Module.StringLiteralContext.Key,
4169 data: Value,
55274170 };
55284171
55294172 pub const Aggregate = struct {
......@@ -5533,156 +4176,42 @@ pub const Value = extern union {
55334176 data: []Value,
55344177 };
55354178
5536 pub const Slice = struct {
5537 base: Payload,
5538 data: struct {
5539 ptr: Value,
5540 len: Value,
5541 },
5542
5543 pub const ptr_index = 0;
5544 pub const len_index = 1;
5545 };
5546
5547 pub const Ty = struct {
5548 base: Payload,
5549 data: Type,
5550 };
5551
5552 pub const IntType = struct {
5553 pub const base_tag = Tag.int_type;
5554
5555 base: Payload = Payload{ .tag = base_tag },
5556 data: struct {
5557 bits: u16,
5558 signed: bool,
5559 },
5560 };
5561
5562 pub const Float_16 = struct {
5563 pub const base_tag = Tag.float_16;
5564
5565 base: Payload = .{ .tag = base_tag },
5566 data: f16,
5567 };
5568
5569 pub const Float_32 = struct {
5570 pub const base_tag = Tag.float_32;
5571
5572 base: Payload = .{ .tag = base_tag },
5573 data: f32,
5574 };
5575
5576 pub const Float_64 = struct {
5577 pub const base_tag = Tag.float_64;
5578
5579 base: Payload = .{ .tag = base_tag },
5580 data: f64,
5581 };
5582
5583 pub const Float_80 = struct {
5584 pub const base_tag = Tag.float_80;
5585
5586 base: Payload = .{ .tag = base_tag },
5587 data: f80,
5588 };
5589
5590 pub const Float_128 = struct {
5591 pub const base_tag = Tag.float_128;
5592
5593 base: Payload = .{ .tag = base_tag },
5594 data: f128,
5595 };
5596
5597 pub const Error = struct {
5598 base: Payload = .{ .tag = .@"error" },
5599 data: struct {
5600 /// `name` is owned by `Module` and will be valid for the entire
5601 /// duration of the compilation.
5602 /// TODO revisit this when we have the concept of the error tag type
5603 name: []const u8,
5604 },
5605 };
5606
5607 pub const InferredAlloc = struct {
5608 pub const base_tag = Tag.inferred_alloc;
5609
5610 base: Payload = .{ .tag = base_tag },
5611 data: struct {
5612 /// The value stored in the inferred allocation. This will go into
5613 /// peer type resolution. This is stored in a separate list so that
5614 /// the items are contiguous in memory and thus can be passed to
5615 /// `Module.resolvePeerTypes`.
5616 prongs: std.MultiArrayList(struct {
5617 /// The dummy instruction used as a peer to resolve the type.
5618 /// Although this has a redundant type with placeholder, this is
5619 /// needed in addition because it may be a constant value, which
5620 /// affects peer type resolution.
5621 stored_inst: Air.Inst.Ref,
5622 /// The bitcast instruction used as a placeholder when the
5623 /// new result pointer type is not yet known.
5624 placeholder: Air.Inst.Index,
5625 }) = .{},
5626 /// 0 means ABI-aligned.
5627 alignment: u32,
5628 },
5629 };
5630
5631 pub const InferredAllocComptime = struct {
5632 pub const base_tag = Tag.inferred_alloc_comptime;
5633
5634 base: Payload = .{ .tag = base_tag },
5635 data: struct {
5636 decl_index: Module.Decl.Index,
5637 /// 0 means ABI-aligned.
5638 alignment: u32,
5639 },
5640 };
5641
56424179 pub const Union = struct {
56434180 pub const base_tag = Tag.@"union";
56444181
56454182 base: Payload = .{ .tag = base_tag },
5646 data: struct {
4183 data: Data,
4184
4185 pub const Data = struct {
56474186 tag: Value,
56484187 val: Value,
5649 },
4188 };
56504189 };
56514190 };
56524191
5653 /// Big enough to fit any non-BigInt value
5654 pub const BigIntSpace = struct {
5655 /// The +1 is headroom so that operations such as incrementing once or decrementing once
5656 /// are possible without using an allocator.
5657 limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb,
5658 };
4192 pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;
56594193
5660 pub const zero = initTag(.zero);
5661 pub const one = initTag(.one);
5662 pub const negative_one: Value = .{ .ptr_otherwise = &negative_one_payload.base };
5663 pub const undef = initTag(.undef);
5664 pub const @"void" = initTag(.void_value);
5665 pub const @"null" = initTag(.null_value);
5666 pub const @"false" = initTag(.bool_false);
5667 pub const @"true" = initTag(.bool_true);
4194 pub const zero_usize: Value = .{ .ip_index = .zero_usize, .legacy = undefined };
4195 pub const zero_u8: Value = .{ .ip_index = .zero_u8, .legacy = undefined };
4196 pub const zero_comptime_int: Value = .{ .ip_index = .zero, .legacy = undefined };
4197 pub const one_comptime_int: Value = .{ .ip_index = .one, .legacy = undefined };
4198 pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one, .legacy = undefined };
4199 pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };
4200 pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined };
4201 pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined };
4202 pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined };
4203 pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined };
4204 pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .legacy = undefined };
4205
4206 pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined };
4207 pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined };
4208 pub const empty_struct: Value = .{ .ip_index = .empty_struct, .legacy = undefined };
56684209
56694210 pub fn makeBool(x: bool) Value {
56704211 return if (x) Value.true else Value.false;
56714212 }
56724213
5673 pub fn boolToInt(x: bool) Value {
5674 return if (x) Value.one else Value.zero;
5675 }
5676
5677 pub const RuntimeIndex = enum(u32) {
5678 zero = 0,
5679 comptime_field_ptr = std.math.maxInt(u32),
5680 _,
5681
5682 pub fn increment(ri: *RuntimeIndex) void {
5683 ri.* = @intToEnum(RuntimeIndex, @enumToInt(ri.*) + 1);
5684 }
5685 };
4214 pub const RuntimeIndex = InternPool.RuntimeIndex;
56864215
56874216 /// This function is used in the debugger pretty formatters in tools/ to fetch the
56884217 /// Tag to Payload mapping to facilitate fancy debug printing for this type.
......@@ -5691,7 +4220,7 @@ pub const Value = extern union {
56914220 var fields: [tags.len]std.builtin.Type.StructField = undefined;
56924221 for (&fields, tags) |*field, t| field.* = .{
56934222 .name = t.name,
5694 .type = *if (t.value < Tag.no_payload_count) void else @field(Tag, t.name).Type(),
4223 .type = *@field(Tag, t.name).Type(),
56954224 .default_value = null,
56964225 .is_comptime = false,
56974226 .alignment = 0,
......@@ -5713,8 +4242,3 @@ pub const Value = extern union {
57134242 }
57144243 }
57154244};
5716
5717var negative_one_payload: Value.Payload.I64 = .{
5718 .base = .{ .tag = .int_i64 },
5719 .data = -1,
5720};
test/behavior/bugs/1381.zig+1
......@@ -17,6 +17,7 @@ test "union that needs padding bytes inside an array" {
1717 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1818 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1919 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
20 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
2021
2122 var as = [_]A{
2223 A{ .B = B{ .D = 1 } },
test/behavior/bugs/6456.zig+1-1
......@@ -24,7 +24,7 @@ test "issue 6456" {
2424 .alignment = 0,
2525 .name = name,
2626 .type = usize,
27 .default_value = &@as(?usize, null),
27 .default_value = null,
2828 .is_comptime = false,
2929 }};
3030 }
test/behavior/cast.zig+8-8
......@@ -746,8 +746,8 @@ test "peer type resolution: disjoint error sets" {
746746 try expect(error_set_info == .ErrorSet);
747747 try expect(error_set_info.ErrorSet.?.len == 3);
748748 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
749 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three"));
750 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
749 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
750 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
751751 }
752752
753753 {
......@@ -756,8 +756,8 @@ test "peer type resolution: disjoint error sets" {
756756 try expect(error_set_info == .ErrorSet);
757757 try expect(error_set_info.ErrorSet.?.len == 3);
758758 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
759 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three"));
760 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
759 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
760 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
761761 }
762762}
763763
......@@ -778,8 +778,8 @@ test "peer type resolution: error union and error set" {
778778 const error_set_info = @typeInfo(info.ErrorUnion.error_set);
779779 try expect(error_set_info.ErrorSet.?.len == 3);
780780 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
781 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three"));
782 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
781 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
782 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
783783 }
784784
785785 {
......@@ -790,8 +790,8 @@ test "peer type resolution: error union and error set" {
790790 const error_set_info = @typeInfo(info.ErrorUnion.error_set);
791791 try expect(error_set_info.ErrorSet.?.len == 3);
792792 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
793 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three"));
794 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
793 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
794 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
795795 }
796796}
797797
test/behavior/type_info.zig+2-2
......@@ -214,8 +214,8 @@ test "type info: error set merged" {
214214 try expect(error_set_info == .ErrorSet);
215215 try expect(error_set_info.ErrorSet.?.len == 3);
216216 try expect(mem.eql(u8, error_set_info.ErrorSet.?[0].name, "One"));
217 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Three"));
218 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Two"));
217 try expect(mem.eql(u8, error_set_info.ErrorSet.?[1].name, "Two"));
218 try expect(mem.eql(u8, error_set_info.ErrorSet.?[2].name, "Three"));
219219}
220220
221221test "type info: enum info" {
test/cases/compile_errors/access_non-existent_member_of_error_set.zig-1
......@@ -9,4 +9,3 @@ comptime {
99// target=native
1010//
1111// :3:18: error: no error named 'Bar' in 'error{A}'
12// :1:13: note: error set declared here
test/cases/compile_errors/compile_log_statement_inside_function_which_must_be_comptime_evaluated.zig+1-1
......@@ -14,4 +14,4 @@ export fn entry() void {
1414// :2:5: error: found compile log statement
1515//
1616// Compile Log Output:
17// @as(*const [3:0]u8, "i32\x00")
17// @as(*const [3:0]u8, "i32")
test/cases/compile_errors/explicit_error_set_cast_known_at_comptime_violates_error_sets.zig+3-4
......@@ -1,5 +1,5 @@
1const Set1 = error {A, B};
2const Set2 = error {A, C};
1const Set1 = error{ A, B };
2const Set2 = error{ A, C };
33comptime {
44 var x = Set1.B;
55 var y = @errSetCast(Set2, x);
......@@ -10,5 +10,4 @@ comptime {
1010// backend=stage2
1111// target=native
1212//
13// :5:13: error: 'error.B' not a member of error set 'error{A,C}'
14// :2:14: note: error set declared here
13// :5:13: error: 'error.B' not a member of error set 'error{C,A}'
test/cases/compile_errors/implicit_cast_of_error_set_not_a_subset.zig+3-3
......@@ -1,5 +1,5 @@
1const Set1 = error{A, B};
2const Set2 = error{A, C};
1const Set1 = error{ A, B };
2const Set2 = error{ A, C };
33export fn entry() void {
44 foo(Set1.B);
55}
......@@ -12,5 +12,5 @@ fn foo(set1: Set1) void {
1212// backend=stage2
1313// target=native
1414//
15// :7:19: error: expected type 'error{A,C}', found 'error{A,B}'
15// :7:19: error: expected type 'error{C,A}', found 'error{A,B}'
1616// :7:19: note: 'error.B' not a member of destination error set
test/cases/compile_errors/int_to_err_non_global_invalid_number.zig+1-2
......@@ -16,5 +16,4 @@ comptime {
1616// backend=llvm
1717// target=native
1818//
19// :11:13: error: 'error.B' not a member of error set 'error{A,C}'
20// :5:14: note: error set declared here
19// :11:13: error: 'error.B' not a member of error set 'error{C,A}'
test/cases/compile_errors/invalid_non-exhaustive_enum_to_union.zig+1-1
......@@ -24,5 +24,5 @@ export fn bar() void {
2424//
2525// :12:16: error: runtime coercion to union 'tmp.U' from non-exhaustive enum
2626// :1:11: note: enum declared here
27// :17:16: error: union 'tmp.U' has no tag with value '15'
27// :17:16: error: union 'tmp.U' has no tag with value '@intToEnum(tmp.E, 15)'
2828// :6:11: note: union declared here
test/cases/compile_errors/pointer_attributes_checked_when_coercing_pointer_to_anon_literal.zig+2-2
......@@ -16,9 +16,9 @@ comptime {
1616// backend=stage2
1717// target=native
1818//
19// :2:29: error: expected type '[][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
19// :2:29: error: expected type '[][]const u8', found '*const struct{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
2020// :2:29: note: cast discards const qualifier
21// :6:31: error: expected type '*[2][]const u8', found '*const tuple{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
21// :6:31: error: expected type '*[2][]const u8', found '*const struct{comptime *const [5:0]u8 = "hello", comptime *const [5:0]u8 = "world"}'
2222// :6:31: note: cast discards const qualifier
2323// :11:19: error: expected type '*tmp.S', found '*const struct{comptime a: comptime_int = 2}'
2424// :11:19: note: cast discards const qualifier
test/cases/compile_errors/return_invalid_type_from_test.zig+4-2
......@@ -1,8 +1,10 @@
1test "example" { return 1; }
1test "example" {
2 return 1;
3}
24
35// error
46// backend=stage2
57// target=native
68// is_test=1
79//
8// :1:25: error: expected type '@typeInfo(@typeInfo(@TypeOf(tmp.test.example)).Fn.return_type.?).ErrorUnion.error_set!void', found 'comptime_int'
\ No newline at end of file
10// :2:12: error: expected type 'anyerror!void', found 'comptime_int'
test/cases/compile_errors/tagName_on_invalid_value_of_non-exhaustive_enum.zig+2-2
......@@ -1,5 +1,5 @@
11test "enum" {
2 const E = enum(u8) {A, B, _};
2 const E = enum(u8) { A, B, _ };
33 _ = @tagName(@intToEnum(E, 5));
44}
55
......@@ -8,5 +8,5 @@ test "enum" {
88// target=native
99// is_test=1
1010//
11// :3:9: error: no field with value '5' in enum 'test.enum.E'
11// :3:9: error: no field with value '@intToEnum(tmp.test.enum.E, 5)' in enum 'test.enum.E'
1212// :2:15: note: declared here
test/cases/compile_errors/tuple_init_edge_cases.zig+1-1
......@@ -41,4 +41,4 @@ pub export fn entry5() void {
4141// :12:14: error: missing tuple field with index 1
4242// :17:14: error: missing tuple field with index 1
4343// :29:14: error: expected at most 2 tuple fields; found 3
44// :34:30: error: index '2' out of bounds of tuple 'tuple{comptime comptime_int = 123, u32}'
44// :34:30: error: index '2' out of bounds of tuple 'struct{comptime comptime_int = 123, u32}'
test/cases/compile_errors/type_mismatch_with_tuple_concatenation.zig+1-1
......@@ -7,4 +7,4 @@ export fn entry() void {
77// backend=stage2
88// target=native
99//
10// :3:11: error: expected type '@TypeOf(.{})', found 'tuple{comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3}'
10// :3:11: error: expected type '@TypeOf(.{})', found 'struct{comptime comptime_int = 1, comptime comptime_int = 2, comptime comptime_int = 3}'
tools/lldb_pretty_printers.py+114-19
......@@ -115,7 +115,7 @@ class zig_Slice_SynthProvider:
115115 try: return int(name.removeprefix('[').removesuffix(']'))
116116 except: return -1
117117 def get_child_at_index(self, index):
118 if index < 0 or index >= self.len: return None
118 if index not in range(self.len): return None
119119 try: return self.ptr.CreateChildAtOffset('[%d]' % index, index * self.elem_size, self.elem_type)
120120 except: return None
121121
......@@ -176,7 +176,7 @@ class zig_TaggedUnion_SynthProvider:
176176 def get_child_index(self, name):
177177 try: return ('tag', 'payload').index(name)
178178 except: return -1
179 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None
179 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None
180180
181181# Define Zig Standard Library
182182
......@@ -196,7 +196,7 @@ class std_SegmentedList_SynthProvider:
196196 except: return -1
197197 def get_child_at_index(self, index):
198198 try:
199 if index < 0 or index >= self.len: return None
199 if index not in range(self.len): return None
200200 prealloc_item_count = len(self.prealloc_segment)
201201 if index < prealloc_item_count: return self.prealloc_segment.child[index]
202202 prealloc_exp = prealloc_item_count.bit_length() - 1
......@@ -231,7 +231,7 @@ class std_MultiArrayList_SynthProvider:
231231 except: return -1
232232 def get_child_at_index(self, index):
233233 try:
234 if index < 0 or index >= self.len: return None
234 if index not in range(self.len): return None
235235 offset = 0
236236 data = lldb.SBData()
237237 for field in self.entry_type.fields:
......@@ -266,7 +266,7 @@ class std_MultiArrayList_Slice_SynthProvider:
266266 except: return -1
267267 def get_child_at_index(self, index):
268268 try:
269 if index < 0 or index >= self.len: return None
269 if index not in range(self.len): return None
270270 data = lldb.SBData()
271271 for field in self.entry_type.fields:
272272 field_type = field.type.GetPointeeType()
......@@ -328,7 +328,7 @@ class std_Entry_SynthProvider:
328328 def has_children(self): return self.num_children() != 0
329329 def num_children(self): return len(self.children)
330330 def get_child_index(self, name): return self.indices.get(name)
331 def get_child_at_index(self, index): return self.children[index].deref if index >= 0 and index < len(self.children) else None
331 def get_child_at_index(self, index): return self.children[index].deref if index in range(len(self.children)) else None
332332
333333# Define Zig Stage2 Compiler
334334
......@@ -345,11 +345,17 @@ class TagAndPayload_SynthProvider:
345345 def get_child_index(self, name):
346346 try: return ('tag', 'payload').index(name)
347347 except: return -1
348 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None
348 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None
349349
350def Inst_Ref_SummaryProvider(value, _=None):
350def Zir_Inst__Zir_Inst_Ref_SummaryProvider(value, _=None):
351351 members = value.type.enum_members
352 return value if any(value.unsigned == member.unsigned for member in members) else 'instructions[%d]' % (value.unsigned - len(members))
352 # ignore .var_args_param_type and .none
353 return value if any(value.unsigned == member.unsigned for member in members) else 'instructions[%d]' % (value.unsigned + 2 - len(members))
354
355def Air_Inst__Air_Inst_Ref_SummaryProvider(value, _=None):
356 members = value.type.enum_members
357 # ignore .var_args_param_type and .none
358 return value if any(value.unsigned == member.unsigned for member in members) else 'instructions[%d]' % (value.unsigned + 2 - len(members))
353359
354360class Module_Decl__Module_Decl_Index_SynthProvider:
355361 def __init__(self, value, _=None): self.value = value
......@@ -359,7 +365,7 @@ class Module_Decl__Module_Decl_Index_SynthProvider:
359365 mod = frame.FindVariable('mod') or frame.FindVariable('module')
360366 if mod: break
361367 else: return
362 self.ptr = mod.GetChildMemberWithName('allocated_decls').GetChildAtIndex(self.value.unsigned).Clone('decl')
368 self.ptr = mod.GetChildMemberWithName('allocated_decls').GetChildAtIndex(self.value.unsigned).address_of.Clone('decl')
363369 except: pass
364370 def has_children(self): return True
365371 def num_children(self): return 1
......@@ -392,7 +398,7 @@ class TagOrPayloadPtr_SynthProvider:
392398 def get_child_index(self, name):
393399 try: return ('tag', 'payload').index(name)
394400 except: return -1
395 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index >= 0 and index < 2 else None
401 def get_child_at_index(self, index): return (self.tag, self.payload)[index] if index in range(2) else None
396402
397403def Module_Decl_name(decl):
398404 error = lldb.SBError()
......@@ -407,6 +413,89 @@ def Module_Decl_RenderFullyQualifiedName(decl): return '.'.join((Module_Namespac
407413
408414def OwnerDecl_RenderFullyQualifiedName(payload): return Module_Decl_RenderFullyQualifiedName(payload.GetChildMemberWithName('owner_decl').GetChildMemberWithName('decl'))
409415
416def InternPool_Find(thread):
417 for frame in thread:
418 ip = frame.FindVariable('ip') or frame.FindVariable('intern_pool')
419 if ip: return ip
420 mod = frame.FindVariable('mod') or frame.FindVariable('module')
421 if mod:
422 ip = mod.GetChildMemberWithName('intern_pool')
423 if ip: return ip
424
425class InternPool_Index_SynthProvider:
426 def __init__(self, value, _=None): self.value = value
427 def update(self):
428 try:
429 index_type = self.value.type
430 for helper in self.value.target.FindFunctions('%s.dbHelper' % index_type.name, lldb.eFunctionNameTypeFull):
431 ptr_self_type, ptr_tag_to_encoding_map_type = helper.function.type.GetFunctionArgumentTypes()
432 if ptr_self_type.GetPointeeType() == index_type: break
433 else: return
434 tag_to_encoding_map = {field.name: field.type for field in ptr_tag_to_encoding_map_type.GetPointeeType().fields}
435
436 ip = InternPool_Find(self.value.thread)
437 if not ip: return
438 self.item = ip.GetChildMemberWithName('items').GetChildAtIndex(self.value.unsigned)
439 extra = ip.GetChildMemberWithName('extra').GetChildMemberWithName('items')
440 self.tag = self.item.GetChildMemberWithName('tag').Clone('tag')
441 self.data = None
442 self.trailing = None
443 data = self.item.GetChildMemberWithName('data')
444 encoding_type = tag_to_encoding_map[self.tag.value]
445 dynamic_values = {}
446 for encoding_field in encoding_type.fields:
447 if encoding_field.name == 'data':
448 if encoding_field.type.IsPointerType():
449 data_type = encoding_field.type.GetPointeeType()
450 extra_index = data.unsigned
451 self.data = extra.GetChildAtIndex(extra_index).Cast(data_type).Clone('data')
452 extra_index += data_type.num_fields
453 else:
454 self.data = data.Cast(encoding_field.type).Clone('data')
455 elif encoding_field.name == 'trailing':
456 trailing_data = lldb.SBData()
457 for trailing_field in encoding_field.type.fields:
458 trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)
459 trailing_len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
460 trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, trailing_data.GetAddressByteSize()))
461 extra_index += trailing_len
462 self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type)
463 else:
464 for path in encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split(' orelse '):
465 if path.startswith('data.'):
466 root = self.data
467 path = path[len('data'):]
468 else: return
469 dynamic_value = root.GetValueForExpressionPath(path)
470 if dynamic_value:
471 dynamic_values[encoding_field.name] = dynamic_value
472 break
473 except: pass
474 def has_children(self): return True
475 def num_children(self): return 2 + (self.trailing is not None)
476 def get_child_index(self, name):
477 try: return ('tag', 'data', 'trailing').index(name)
478 except: return -1
479 def get_child_at_index(self, index): return (self.tag, self.data, self.trailing)[index] if index in range(3) else None
480
481def InternPool_NullTerminatedString_SummaryProvider(value, _=None):
482 try:
483 ip = InternPool_Find(value.thread)
484 if not ip: return
485 items = ip.GetChildMemberWithName('string_bytes').GetChildMemberWithName('items')
486 b = bytearray()
487 i = 0
488 while True:
489 x = items.GetChildAtIndex(value.unsigned + i).GetValueAsUnsigned()
490 if x == 0: break
491 b.append(x)
492 i += 1
493 s = b.decode(encoding='utf8', errors='backslashreplace')
494 s1 = s if s.isprintable() else ''.join((c if c.isprintable() else '\\x%02x' % ord(c) for c in s))
495 return '"%s"' % s1
496 except:
497 pass
498
410499def type_Type_pointer(payload):
411500 pointee_type = payload.GetChildMemberWithName('pointee_type')
412501 sentinel = payload.GetChildMemberWithName('sentinel').GetChildMemberWithName('child')
......@@ -468,8 +557,8 @@ type_tag_handlers = {
468557 'empty_struct_literal': lambda payload: '@TypeOf(.{})',
469558
470559 'anyerror_void_error_union': lambda payload: 'anyerror!void',
471 'const_slice_u8': lambda payload: '[]const u8',
472 'const_slice_u8_sentinel_0': lambda payload: '[:0]const u8',
560 'slice_const_u8': lambda payload: '[]const u8',
561 'slice_const_u8_sentinel_0': lambda payload: '[:0]const u8',
473562 'fn_noreturn_no_args': lambda payload: 'fn() noreturn',
474563 'fn_void_no_args': lambda payload: 'fn() void',
475564 'fn_naked_noreturn_no_args': lambda payload: 'fn() callconv(.Naked) noreturn',
......@@ -495,7 +584,7 @@ type_tag_handlers = {
495584 'many_mut_pointer': lambda payload: '[*]%s' % type_Type_SummaryProvider(payload),
496585 'c_const_pointer': lambda payload: '[*c]const %s' % type_Type_SummaryProvider(payload),
497586 'c_mut_pointer': lambda payload: '[*c]%s' % type_Type_SummaryProvider(payload),
498 'const_slice': lambda payload: '[]const %s' % type_Type_SummaryProvider(payload),
587 'slice_const': lambda payload: '[]const %s' % type_Type_SummaryProvider(payload),
499588 'mut_slice': lambda payload: '[]%s' % type_Type_SummaryProvider(payload),
500589 'int_signed': lambda payload: 'i%d' % payload.unsigned,
501590 'int_unsigned': lambda payload: 'u%d' % payload.unsigned,
......@@ -611,13 +700,19 @@ def __lldb_init_module(debugger, _=None):
611700 add(debugger, category='zig.stage2', type='Zir.Inst', identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
612701 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Zir\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
613702 add(debugger, category='zig.stage2', regex=True, type='^Zir\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True)
614 add(debugger, category='zig.stage2', type='Zir.Inst::Zir.Inst.Ref', identifier='Inst_Ref', summary=True)
703 add(debugger, category='zig.stage2', type='Zir.Inst::Zir.Inst.Ref', summary=True)
615704 add(debugger, category='zig.stage2', type='Air.Inst', identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
705 add(debugger, category='zig.stage2', type='Air.Inst::Air.Inst.Ref', summary=True)
616706 add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True)
617707 add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True)
618708 add(debugger, category='zig.stage2', type='Module.Decl::Module.Decl.Index', synth=True)
619 add(debugger, category='zig.stage2', type='type.Type', identifier='TagOrPayloadPtr', synth=True)
620 add(debugger, category='zig.stage2', type='type.Type', summary=True)
621 add(debugger, category='zig.stage2', type='value.Value', identifier='TagOrPayloadPtr', synth=True)
622 add(debugger, category='zig.stage2', type='value.Value', summary=True)
709 add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True)
710 add(debugger, category='zig.stage2', type='InternPool.Index', synth=True)
711 add(debugger, category='zig.stage2', type='InternPool.NullTerminatedString', summary=True)
712 add(debugger, category='zig.stage2', type='InternPool.Key', identifier='zig_TaggedUnion', synth=True)
713 add(debugger, category='zig.stage2', type='InternPool.Key.Int.Storage', identifier='zig_TaggedUnion', synth=True)
714 add(debugger, category='zig.stage2', type='InternPool.Key.ErrorUnion.Value', identifier='zig_TaggedUnion', synth=True)
715 add(debugger, category='zig.stage2', type='InternPool.Key.Float.Storage', identifier='zig_TaggedUnion', synth=True)
716 add(debugger, category='zig.stage2', type='InternPool.Key.Ptr.Addr', identifier='zig_TaggedUnion', synth=True)
717 add(debugger, category='zig.stage2', type='InternPool.Key.Aggregate.Storage', identifier='zig_TaggedUnion', synth=True)
623718 add(debugger, category='zig.stage2', type='arch.x86_64.CodeGen.MCValue', identifier='zig_TaggedUnion', synth=True, inline_children=True, summary=True)
tools/stage2_gdb_pretty_printers.py+1-1
......@@ -18,7 +18,7 @@ class TypePrinter:
1818 'many_mut_pointer': 'Type.Payload.ElemType',
1919 'c_const_pointer': 'Type.Payload.ElemType',
2020 'c_mut_pointer': 'Type.Payload.ElemType',
21 'const_slice': 'Type.Payload.ElemType',
21 'slice_const': 'Type.Payload.ElemType',
2222 'mut_slice': 'Type.Payload.ElemType',
2323 'optional': 'Type.Payload.ElemType',
2424 'optional_single_mut_pointer': 'Type.Payload.ElemType',